25 Ağustos 2020 Salı

PREFER TRY-WITH-RESOURCES TO TRY-FINALLY

Merhaba,

Bu yazimda try-with-resources nedir ve neden kullanmaliyiz, onu anlatmaya calisacagim.

Javada  kullanilan bircok resource manuel olarak close() cagrimi ile kapatilmasi gerekiyor. Burada genelde izlenen yol baglantiyi acip try icinde istedigimiz islemi yapip finally de bu connection i close etmektir.

static String firstLineOfFile(String path) throws IOException { 
BufferedReader br = new BufferedReader(new FileReader(path)); 
    try { 
        return br.readLine(); 
    } finally { 
      br.close(); 
    } 
}
Ama bu yontem artik cok tercih edilen bir yontem degildir. Cunku bir tane daha resource eklendiginde yonetimi zorlasacaktir.


static void copy(String src, String dst) throws IOException { 
    InputStream in = new FileInputStream(src); 
    try { 
    OutputStream out = new FileOutputStream(dst); 
        try { byte[] buf = new byte[BUFFER_SIZE]; 
        int n; 
        while ((n = in.read(buf)) >= 0) 
        out.write(buf, 0, n); 
        } 
        finally { 
            out.close(); 
        } 
    } finally {
     in.close();
    } 
}

Bir de uzerine connection close ederken hata cikarsa onlari da handle etmek gerekir. Yani finally icinde sadece close yapmak yerine tekrar try catch kullanmak gerekir.

Tum bunlardan kurtulmak icin try-with-resources kullanmaliyiz.


static void copy(String src, String dst) throws IOException {
 try (InputStream in = new FileInputStream(src); OutputStream out = new FileOutputStream(dst)) { 
    byte[] buf = new byte[BUFFER_SIZE]; 
    int n; 
    while ((n = in.read(buf)) >= 0)
       out.write(buf, 0, n); 
   } 
}







Yararlandigim kaynak:

Effective Java 3rd Edition

Avoid Creating Unnecessary Objects

Merhaba,

Bu yazimda Effective Java kitabindaki Avoid Creating Unnecessary Objects maddesindeki bir ornekten bahsedecegim. Java da Autoboxing - Unboxing kavramlari


Yapacagimiz islem tum integerlari toplayan bir kod yazmak. Sum'i long olarak tanimladik cunku int deger toplamin sonucunu tutmak icin kucuk kaliyor.

private static long sum() { 
Long sum = 0L;
 for (long i = 0; i <= Integer.MAX_VALUE; i++) 
    sum += i;
return sum;
}

Bu kodu calistirdigimizda sorunsuz calisiyor. Benim bilgisayarimda 8 saniyede calisti.


Bir de sum degerini Long degil de long olarak calistirmayi denedim. Bu durumda ise 1 saniye surdu.

Buradan cikarilacak ders sudur:


Prefer primitives to boxed primitives, and watch out for unintentional autoboxing


Yani diyorki boxed primitive yerine primivite tercih edin.

Boxed olanlar wrapper classlaridir. Onlari kullanmak her zaman gerekli olmayabilir.


Autoboxing Ornegi:


int olan primitive bir degeri Integer Wrapper class olan ArrayList te tutmak

private static List<Integer> sum() { 
List<Integer> list = new ArrayList<>();
 for (int i = 0; i <= 10; i++) 
    list.add(i);
return list;
}


24 Mayıs 2020 Pazar

JAVA 8 STREAM API ORNEKLERI

Merhaba,
Bu yazimda Stream API uzerinden genel ornekler gostermeye calisacagim.

Oncelikle elimizdeki datayi stream e cevirmemiz lazim. Sonra elimizdeki data birden coksa o halde forEach kullanmamiz lazim. 

List names = Arrays.asList("John", "Jack", "Kate", "Sawyer","Hurley", "John");
names.stream().forEach(System.out::println);

  • Burada elimizde bir liste var. ve biz bu listeyi yazdirmak icin once stream e donusturduk. Sonra da hic bir islem yapmadan direkt yazdiracagimiz icin forEach ile donup yazdirdik.

Ciktimiz:
John
Jack
Kate
Sawyer
Hurley
John

Eger data uzerinde kontrol yapmak istiyorsak once kontrolu yapmali sonra datayi gostermeliyiz. Kontrolu filter ile yapip datayi forEach ile gosterecegiz.

  • Isimlerden uzunlugu 4 olanlari gostermeye calisalim:

names.stream().filter(name -> name.length() == 4).forEach(System.out::println);

Gordugumuz gibi once stream e cevirdik. Sonra filter ile kontrolumuzu yaptik. Sonra da 4 olan eleman sayisi 1den cok oldugu icin uzerinde forEach ile donduk ve yazdirdik.

Ciktimiz: 
John
Jack
Kate
John
  • Gordugumuz gibi listede ayni elemandan 2 tane var. Sadece distinct elemanlari gostermek icin distinct() kullanmaliyiz. Bu da bir konrol oldugu icin once stream e cevircez sonra distinct kontrolu yapicaz, sonra da bulduklarimizi yazdirmak icin forEach cagiracagiz.
names.stream().distinct().forEach(System.out::println);
Ciktimiz:

John
Jack
Kate
Sawyer
Hurley
  • Simdi de listemizdeki elemanlari siralayalim ve bunu gosterelim. Bu da bir kontrol old icin once stream, sonra sirala sonra da forEach ile goster.
names.stream().sort().forEach(System.out::println); 

Ciktimiz:
Hurley
Jack
John
John
Kate
Sawyer

  • Simdi ise listemizdeki isimleri upper case 'e donusturelim. Burada map kullanacagiz. Map fonksiyon alir ve veriyi donusturmek icin kullanilir.
names.stream().map(name -> name.toUpperCase()).forEach(System.out::println);

Ciktimiz:

JOHN
JACK
KATE
SAWYER
HURLEY
JOHN

  • 1 ile 5 arasindaki sayilarin karesini hesaplayalim:
IntStream.rangeClosed(1, 5).map(i -> i* i).forEach(System.out::println);
Ciktimiz:
1
4
9
16
25

REDUCE

Reduce, ise 2 parametre alir. Bir baslangic degeri, digeri ise onceki sonuc. Yani bir onceki islemin sonucu digerine input olarak verilir.

  • 1'den 5'e kadar olan sayilarin toplamini bulalim. bir onceki sonuc digerine input olacagi icin reduce'u kullanabiliriz.
int result = IntStream.rangeClosed(1, 5).reduce(0, (prev, next) -> prev + next);

Burada result 15 olarak hesaplanir.

MAP VE REDUCE BIRLIKTE KULLANIMI

Simdi de map ve reduce birlikte kullanimini gorelim. Person adinda bir classimiz olsun ve tum personlarimizin yaslarinin ortalamasini hesaplamak isteyelim.

public class Person {
   private String name;
   private Integer age;
   public Person(String name, Integer age) {
	super();
	this.name = name;
	this.age = age;
}
public String getName() {
	return name;
}
public void setName(String name) {
	this.name = name;
}
public Integer getAge() {
	return age;
}
public void setAge(Integer age) {
	this.age = age;
}    
}


Ortalama icin de :

Person p1 = new Person("John", 12);
Person p2 = new Person("Jack", 20);
Person p3 = new Person("Kate", 30);
Person p4 = new Person("Sawyer", 51);
Person p5 = new Person("Hurley", 60);
List personList = Arrays.asList(p1, p2, p3, p4, p5);
double ortalama = personList.stream().map(p -> p.getAge()).map(Double::valueOf).reduce(0, (a, b) -> (a+b)/2);

Eger yas degeri null olan varsa ortalamaya dahil etmemek icin de asagidaki gibi yapabiliriz.

personList.stream().filter(Objects:nonNull).map(p -> p.getAge()).map(Double::valueOf).reduce(0, (a,b) -> (a+b)/2;)

  • Kitaplari sayfalarina gore artan siraya dizelim:
Book book1 = new Book("Clean Code", "Robert Cecil Martin", 300);
Book book2 = new Book("Test Driven Development", "Kent Beck", 450);
Book book3 = new Book("Refactoring", "Martin Fowler", 200);
List<Book> bookList = Arrays.asList(book1, book2, book3);
bookList.stream().sorted(Comparator.comparingInt(Book::getPage)).collect(Collectors.toList());


23 Mayıs 2020 Cumartesi

React Context API Example

Merhaba,
Bu yazimda konuu daha iyi anlamak icin bir react context api ornegi daha yapacagim. 
Context Api 'in amaci datayi her yerden ulasabilir kilmakti (componentlar arasinda tek tek tasimak uzun bir is cunku)

Bu ornegimizde bir butonumuz olacak. Bu butona basilinca kurbaga sesi cikaracak ve tekrar basinca sessiz olacak. Bunun icin bir context yazalim.

context.js

import React from 'react';
const FrogContext = React.createContext();
const reducer = (state, action) => {
	if(action.type == "TOGGLE"){
		return {...state, isAFrog : !state.isAFrog};
	}
}
export class FrogProvider extends Component {
state = {
	isAFrog : false,
	dispatch: action => {
		this.setState(state => reducer(state, action));
	}
};
render() {
 return (
	{this.props.children}
		)
	}
}
const FrogConsumer = FrogContext.Consumer;
export default FrogConsumer;

Burada gordugumuz gibi dispacthde reducer'i cagirdik. Bunu tetiklemek kaldi simdi de.
dispatch cagrildiginda state icindeki isAFrog degerini degistiriyoruz.

Simdi componentimize gelelim:


import React, { Component } from 'react'
import FrogConsumer from '../context';

export default class frogs extends Component {
    render() {
        return (
           <FrogConsumer>
               {({isAFrog, dispatch}) => {
                   return (
                       <div>
                           <div>{isAFrog ? "🐸 croak" : "...silence..."}</div>
                           <button onClick={ e=> dispatch({type: "TOGGLE"})}>
                               Change
                           </button>
                       </div>
                   )
               }}
           </FrogConsumer>
        )
    }
}



Butona tikladiktan sonra ise asagidaki gibi olacak



17 Mayıs 2020 Pazar

JAVA CLONING - DIFFERENCE BETWEEN DEEP CLONE AND SHALLOW CLONE

Merhaba,
Bu yazimda javada clonelamayi anlatmaya calisacagim. Clonelamak var olan objemizin aynisindan bir tane daha olusturmaktir. 

Java'da Object classinda clone() methodu ile objemizin aynisindan bir tane daha yaratabiliriz. Ama her obje clonelanmaz. Clonelayabilmek icin classlarimizin Cloneable interface'ini implement etmeleri gerekir. 

Default olarak clone() methodu shallow copy yapar. Bizim deep copy yapabilmemiz icin clone() methodunu override etmemiz gerekir.



Oncelikle shallow copy e bakalim.

SHALLOW COPY

Shallow copy de objenin aynisi uzerinden kopyalama yapilir. 
 
class Course{
	String subject1;
	String subject2;
	String subject3;
	
	public Course(String subject1, String subject2, String subject3) {
		this.subject1 = subject1;
		this.subject2 = subject2;
		this.subject3 = subject3;
	}
}

class Student implements Cloneable{
	int id;
	String name;
	Course course;
	
	public Student(int id, String name, Course course) {
		this.id = id;
		this.name = name;
		this.course = course;
	}
	
	protected Object clone() throws CloneNotSupportedException{
		return super.clone();
	}
}

public class ShallowCopy {

	public static void main(String[] args) {
		Course science = new Course("Physics", "Chemistry", "Biology");
		Student student1 = new Student(1, "Joe", science);
		Student student2 = null;
		
		try {
			student2 = (Student) student1.clone();
		} catch (CloneNotSupportedException e) {
			e.printStackTrace();
		}
		System.out.println(student1.course.subject3);
		student2.course.subject3 = "Math";
		System.out.println(student1.course.subject3);
	}

}
Output

Biology
Math

Gordugumuz gibi student2 nin yani clone objemizin degerini degistirdigimizde orjinal objemizinde degeri degisti.

DEEP COPY

Deep clone yaptigimizda ise clone() methodunu override etmemiz gerekir. Deep te de shallow gibi objenin aynisi olusturulur ancak 2 objenin referansi birbirinden farklidir.

Bu durumda birinde yapilan degisiklik digerini etkilemez.

class Course implements Cloneable{
	String subject1;
	String subject2;
	String subject3;
	
	public Course(String subject1, String subject2, String subject3) {
		this.subject1 = subject1;
		this.subject2 = subject2;
		this.subject3 = subject3;
	}
	protected Object clone() throws CloneNotSupportedException {
		return super.clone();
	}
}

class Student implements Cloneable{
	int id;
	String name;
	Course course;
	
	public Student(int id, String name, Course course) {
		this.id = id;
		this.name = name;
		this.course = course;
	}
	
	protected Object clone() throws CloneNotSupportedException {
		Student student = (Student) super.clone();
		student.course = (Course) course.clone();
		return student;
	}
}

public class DeepClone {

	public static void main(String[] args) {
		Course science = new Course("Physics", "Chemistry", "Biology");
		Student student1 = new Student(1, "Joe", science);
                Student student2 = null;
        
                try {
			student2 = (Student) student1.clone();
		} catch (CloneNotSupportedException e) {
			e.printStackTrace();
		}
                System.out.println(student1.course.subject3);
		student2.course.subject3 = "Math";
		System.out.println(student1.course.subject3);
	}

}
Output:
Biology
Biology


Genel olarak bu sekilde.

2 Mayıs 2020 Cumartesi

CONTEXT API NEDIR - REACT REDUX GIRIS

Bu yazimdaki daha once baslamis oldugum React derslerindeki ornekler uzerinden devam edecegim.
Simdi ise daha once state kullanarak yapmis oldugumuz ornekleri Context API kullanarak yapmayi gorecegiz. Onceki yazima bu linkten ulasabilirsiniz.

Uygulamanin son halini ise githubdan gorebilirsiniz : https://github.com/geallen/react_projects

En son ne yaptigimizi bir hatirlayalim.

App icinde bir celebriys array i olusturmustuk. Ve Celebrity icinde bunu kullanmak icin tasiyorduk. Daha sonra herbir celebrity i ekranda gosteriyorduk. Yani datayi componentlerde kullanmak icin tek tek gezdiriyorduk. Bu yontem hic efektif degil ve buyuk uygulamalarda tercih edilmiyor.

Bunun icin Context Api yapisini kullanacagiz. Celebritys datasini ortak bir yerde olusturup tum componentlerde ona erismek daha uygun bir yontem. Bunun icin Provider ve Consumer yapisina ihtiyacimiz var. Oncelikle Celebritys i bize provide etmeli. Biz de onu consume etmeli ve ekranda gosterebilmeliyiz.

Bunun icin oncelikle context.js adinda bir dosya olusturuyoruz. Contextimizi burada olusturacagiz.

Contextin icinde datalarimizi setliyoruz ve provider icinde gnderiyoruz, Consumer ile de export ediyoruz ki baskalari kullanabilsin.

import React, { Component } from 'react'

const CelebrityContext = React.createContext();

export class CelebrityProvider extends Component {
    state = {
        users : [
            {
              id: 1,
              name : "Monica Geller",
              movie : "Friends",
              age : "28"
            },
            {
              id: 2,              
              name : "John Locke",
              movie : "Lost",
             age : "43"
            },
            {
              id: 3,
              name : "Ted Mosby",
              movie : "HIMYM",
              age : "35"
            }
          ]
    }
   render() {
        return (
            <div>
                <CelebrityContext.Provider value= {this.state}>
                   {this.props.children}
              </CelebrityContext.Provider>
            </div>
        )
    }
}
const CelebrityConsumer = CelebrityContext.Consumer;
export default CelebrityConsumer;

En sonda da contextten Celebrityconsumer olusturmaliyiz ki bunu kullanabilelim.

Daha sonra index.js e gecip App componentimizi CelebrityProvider ile saralim ki bu provider App in her yerinden erisilebilsin.

import {CelebrityProvider} from './context';
ReactDOM.render(
  <React.StrictMode>
    <CelebrityProvider>
      <App />
    </CelebrityProvider>,
 </React.StrictMode>,
  document.getElementById('root')
);


Bu sekilde datalara heryerden erisebilecegiz.

App.js icinde Celebritys componentimizi olusturduk ekranda gosterebilmek icin. Simdi Celebritys.js icine gecelim ve Consumer dan aldigimiz datalari ekranda gostermeye calisalim.

Bunun icin Consumer componentini olusturuyoruz ve consumerdan gelen value'yu(this.state icinde users arrayi vardi) user a atiyoruz.

import React, { Component } from 'react'
import Celebrity from './celebrity';
import CelebrityConsumer from '../context';

export default class celebritys extends React.Component {
    render() {
        return(
            <CelebrityConsumer>
                {
                    value => {
                        const {users} = value;
                        console.log("users"+ users);
                        return (
                            <div>
                                {
                                    users.map(celebrity => {
                                        return (
                                            <Celebrity 
                                             key = {celebrity.id}
                                             id = {celebrity.id}
                                             name = {celebrity.name}
                                             movie = {celebrity.movie}
                                                age = {celebrity.age} />
                                        )
                                    })
                                }
                            </div>
                        )
                    }
                }
            </CelebrityConsumer>
        )        
    }
}

Simdi ise contextapi dar yer alan dispatcher / reducer / acion kavramlarini gorelim.

Oncelikle projemizin son haline bakalim. Ekranda asagidaki gibi celebriyleri siraliyorduk ve isme tiklandiginda item'in detayini gosteriyorduk.Simdi ise yanlarinda yer alan cop kutusuna basildiginda her bir celebrity'i silecegiz ve bunu dispacther ve reducer kullanarak yapacagiz.



Oncelikle yazmis oldugumuz contexte gidelim ve contetimizin state'ine dispatcher ekleyelim.

dispatch : action => {
            this.setState(state => reducer(state, action))
          }

Bu koddan anlamamiz gereken su: dispatch tetiklendiginde bir action parametresi gonderilecek ve biz state'i guncelleyecegiz. Nasil guncelleyecegiz ? reducer fonksiyonunu cagirarak. Reducer ise state ve action parametreleri alip state i guncelleyecek. Simdi reducer i tanimlayalim. Yine context icinde tabiki.

const reducer = (state, action) => {
  switch(action.type){
    case "DELETE_USER":
      return {
        ...state,
        users: state.users.filter(user => action.payload != user.id)
      }
    default:
      return state
  }
}

Evet dedigimiz gibi gelen action tipi Delete_user ise state icindeki users'i guncelleyecegiz. Nasil ?

Koda baktigimizda action icinde iki parametre gonderilmesine ihtiyacimiz oldugunu goruyoruz. Type ve payload olmak uzere. Simdi users'i nasil guncelleyecegimize gelirsek payload olarak gonderilen id haric diger idler users da kalacak. Yani sadece payload icinde gonderilen id silinecek.

Simdi de celebrity componentimize gelelim ve bu parametreleri cop kutusuna tiklaninca gonderelim.

<i className="far fa-trash-alt"  onClick={this.deleteUserOnClick.bind(this, dispatch)} 
 style={{cursor:"pointer"}}></i>


Burada gordugmuz gibi fonksiyona dispacth i gonderdik. Simdi de fonksiyon tanimina bakalim.

deleteUserOnClick = (dispatch, e) =>{
        const {id} = this.props;
        dispatch({type : "DELETE_USER", payload :id})
    }

Yani dispatch i cagir diyoruz. Dispatch icin action parametresine ihtiyacimiz vardi. Onu da gondermis olduk.

Bu sekilde calistirdigimizda itemlerimiz silinecek.


DYNAMIC CSS 

Ekranda yer alan card itemlerimize tiklandiginda acilinca o cardlarimizin background color larini degistirmeye calisalim. Acilip kapanmasini state icndeki isVisible ile yapiyorduk. O halde burada da onu kullanabiliriz.


<div className="card" style={isVisible ? {backgroundColor: '#B0BEC5', 
    color: 'white'} : null}>
  <div className="card-header d-flex justify-content-between">
  <h4 className="d-inline" onClick= {this.onClickName}>{name}</h4>
  <i className="far fa-trash-alt" 
onClick= {this.deleteUserOnClick.bind(this, dispatch)}  
style={{cursor:"pointer"}}></i>
           </div>
             { isVisible ? 
            <div className="card-body">
                <p className="card-text">Movie : {movie}</p>
                <p className="card-text">Age : {age}</p>
            </div>
            : null}
            </div> 


ADDING OBJECT TO STATE LIST

En son ornegimizde celebrity detaylari gosterme ve silme islemlerini yapmistik. Simdi de bir form olusturup yeni bir celebrity ekleme islemlerini yapalim.

import React, { Component } from 'react'
import posed from 'react-pose';
import CelebrityConsumer from '../context';

var uniqid = require('uniqid');
const Animation = posed.div({
    visible : {
        opacity : 1,
        applyAtStart : {
            display : "block"
        }
    },
    hidden : {
        opacity : 0,
        applyAtEnd : {
            display : "none"
        }
    }
});

export default class addCelebrity extends Component {
    state = {
        visibility : true,
        name : "",
        movie : "",
        age : ""
    }

    changeVisibility = (e) => {
        this.setState({ visibility : !this.state.visibility})
    }

    changeInput = (e) => {
        this.setState({
            [e.target.name: e.target.value
        })
    }

    addCelebrity= (dispatch, e) => {
        e.preventDefault();
        const {name, movie, age} = this.state;
        const newCelebrity = {
            id : uniqid(),
            name,
            movie,
            age 
        }
        dispatch({type : "ADD_USER", payload : newCelebrity});
    }

    render() {
        const {visibility, name, movie, age} = this.state;

        return(
            <CelebrityConsumer>
                {
                    value => {
                        const {dispatch} = value;
                        return (
                          <div className="col-md-8 mb-4">
                 <button className="btn btn-dark btn-block mb-2" 
onClick={this.changeVisibility} >
            {visibility ? 'Hide Form' : 'Show Form'}</button>
<Animation pose={this.state.visibility ?
    'visible' : 'hidden'}>
<div className="card">
<div className="card-header">
<h4>Add Celebrity Form</h4>
 </div>
<div className="card-body">
<form onSubmit = {this.addCelebrity.bind(this,dispatch)}>
<div className="form-group">
    <label htmlFor="name">Name</label>
    <input type="text" name="name" id="id" 
    placeholder="Enter Name" className="form-control"
    value={name} onChange={this.changeInput}></input>
</div>
<div className="form-group">
    <label htmlFor="name">Movie</label>
    <input type="text" name="movie" id="movie" 
    placeholder="Enter Movie" className="form-control"
    value={movie} onChange={this.changeInput}></input>
 </div>
<div className="form-group">
    <label htmlFor="name">Age</label>
    <input type="text" name="age" id="age" 
    placeholder="Enter Age" className="form-control"
     value={age} onChange={this.changeInput}></input>
</div>
<button type="submit" className="btn btn-danger btn-block">
Add Celebrity</button>
</form>
 </div>
 </div>
</Animation>
</div>
 )
}
}
</CelebrityConsumer>
        )        
    }
}


Bu kodun kisaca uzerinden gecelim. Visibility visible ise "Add Celebrity Form " isminde bir form gorunecek. Bu formun animasyon olarak grunup kapanmasi icin Animation componentini kullandik. react-pse dan import ettik. Detaylar icin su linke bakabilirsiniz.

Form icerisinde 3 tane input alani var : Name, Movie, Age olmak uzere.

Bu olusturdugumuz inputlara bir sey yazilamiyor ilk basta. Yazilmasini saglamak icin onChange eventi ekliyoruz her bir input fieldina. 

onChange icin changeInput adinda bir fonksiyon yazdik ve icinde naptigimiza bakalim:

changeInput = (e) => {
        this.setState({
            [e.target.name: e.target.value
        })
    }

Gelen inputlarin namelerinden valuelarini alabiliriz artik bu sekilde.

Form submit edildiginde ise yazdigimiz fonksiyon addCelebrity adinda. Burada aldigimiz dispacth i bind ettik. Simdi de addCelebrity icine bakalim.

addCelebrity= (dispatch, e) => {
        e.preventDefault();
        const {name, movie, age} = this.state;
        const newCelebrity = {
            id : uniqid(),
            name,
            movie,
            age 
        }
        dispatch({type : "ADD_USER", payload : newCelebrity});
    }

e.preventDefault ile form submit edildiginde sayfanin yenilenmesini onluyoruz. 

Yeni bir celebrity olustrduk. Bunu ekleyecegiz. Her yeni celebrity nin id si farkli olmasi icin unique id atamaliyiz.  Bunun icin de uniquie id generate eden bir framework kullanacagiz. 

Su sekilde olusturduk. 
var uniqid = require('uniqid');


Kullanimi icin su linke bakabilirsiniz.

Daha sonra da dispatch icinde bir type ve bir de payload adinda parametre gonderdik.

dispatch({type : "ADD_USER", payload : newCelebrity});

Reducer icinde dispatch'den gelen type'a bakacagiz. Eger ADD_USER ise payload icindeki user'i users listesine ekleyecegiz. Simdi de context icindeki reducer'e gecelim...

const reducer = (state, action) => {
  switch(action.type){
    case "DELETE_USER":
      return {
        ...state,
        users: state.users.filter(user => action.payload !== user.id)
      }
    case "ADD_USER":
        return {
          ...state,
          users: [...state.users, action.payload]
      }    
    default:
      return state
  }
}


ADD_USER ise su sekilde yapmisiz.

...state demek var olan state'in aynisini al demektir. Daha sonra da state icindeki users'i gelen user'i ekleyerek guncellemisiz. Bu durumda users listesi guncellendigi icin yeniden render edilecek ve ekledigimiz celebrity de ekranda gorunecektir.

Add Celebrity Form un gorunumu su sekildedir.


UPDATE OBJECT IN STATE LIST

Celebrity Guncelleme isine bakalim simdi de . Bunun icin sil butonunun yanina bir icon daha ekledim guncellemek icin. Guncelle dedigimde yazdigim fonksiyona bakalim simdi de .

 updateCelebrity = (dispatch, e) => {
        e.preventDefault();
        const {movie, age} = this.state;
        const {name, id} = this.props;
        const celebrity = {
            id,
            name,
            movie,
            age
        }

        dispatch({type: "UPDATE_USER", payload: celebrity})
    }

Simdi de reducer icine bakalim. 

const reducer = (state, action) => {
  switch(action.type){
    case "DELETE_USER":
      return {
        ...state,
        users: state.users.filter(user => action.payload !== user.id)
      }
    case "ADD_USER":
        return {
          ...state,
          users: [...state.users, action.payload]
      }
    case "UPDATE_USER":
let index = action.payload.id;
state.users.find(user => user.id === index).age = action.payload.age;
state.users.find(user => user.id === index).movie=action.payload.movie;

      return {
        ...state
      }
    default:
      return state
  }
}

UPDATE_USER geldiginde state'in user'indan gelen id'li useri buluyorum ve bu user'in age ve movie degerlerini gonderdigim inputtaki degerle guncelliyorum. Daha sonrada state'i return ediyorum.

Projenin son haline github hesabimdan ulasabilirsiniz: https://github.com/geallen/react_projects