State İçerisindeki Dizileri Güncelleme

JavaScript’te diziler mutasyona uğratılabilir (mutable) ancak siz state’te sakladığınız dizileri mutasyona uğratılamaz (immutable) olarak görmelisiniz. Tıpkı nesnelerde olduğu gibi, state’te saklanan bir diziyi güncellemek istediğiniz zaman yeni bir dizi oluşturmanız (veya var olanın bir kopyasını oluşturmanız) ve ardından yeni oluşturduğunuz diziyi kullanmak için state’i güncellemeniz gerekmektedir.

Bunları öğreneceksiniz

  • React state’indeki bir diziye öğeler nasıl eklenir, çıkarılır ya da değiştirilir
  • Bir dizi içindeki nesne nasıl güncellenir
  • Immer kullanarak dizi kopyalama işlemi daha az tekrarla nasıl yapılır

Dizileri mutasyona uğratmadan güncelleme

JavaScript’te diziler de bir tür nesnedir. Nesnelerde olduğu gibi, React state’indeki dizileri salt okunur olarak görmelisiniz. Bu, arr[0] = 'bird' şeklinde bir dizi içindeki öğeleri başka değerlere yeniden atamamanız, ayrıca push() ve pop() gibi dizileri mutasyona uğratan JavaScript metodlarını kullanmamanız gerektiği anlamına gelir.

Bu metodları kullanmak yerine, bir diziyi her güncellemek istediğinizde state setter fonksiyonunuza yeni bir dizi iletmelisiniz. Bunu yapmak için, filter() ve map() gibi diziyi mutasyona uğratmayan JavaScript metodlarını kullanarak orijinal diziden yeni bir dizi oluşturabilirsiniz. Ardından, state’inizi kopyaladığınız dizi olarak güncelleyebilirsiniz.

Aşağıda sık kullanılan dizi metodları tablo halinde gösterilmiştir. React state’indeki dizilerle çalışırken sol sütundaki metodları kullanmaktan kaçınarak sağ sütundaki metodları tercih etmelisiniz.

kaçınılacaklar (diziyi mutasyona uğratır)tercih edilecekler (yeni bir dizi döndürür)
eklemekpush, unshiftconcat, [...arr] spread sözdizimi (örnek)
çıkartmakpop, shift, splicefilter, slice (örnek)
değiştirmeksplice, arr[i] = ... atamasımap (örnek)
sıralamakreverse, sortilk önce diziyi kopyalayın (örnek)

Alternatif olarak, her iki sütundaki metodları kullanmanıza izin veren [Immer’ı] (#write-concise-update-logic-with-immer) tercih edebilirsiniz.

Tuzak

Ne yazık ki, slice ve splice metodları isim olarak benzeseler bile birbirlerinden çok farklıdırlar.

  • slice metodu dizinin bir parçasını veya tamamını kopyalamınızı sağlar.
  • splice diziyi mutasyona uğratır (diziye yeni öğe eklemek ya da var olanı çıkartmak için kullanılır).

React’te, slice (p yok!) metodunu daha sık kullanacaksınız çünkü state’teki nesneleri veya dizileri mutasyona uğratmak istemezsiniz. Nesneleri Güncelleme sayfasında mutasyon nedir ve state için neden kullanılmamalıdır öğrenebilirsiniz.

Bir diziye eklemek

push() metodu diziyi mutasyona uğratacaktır ancak biz bunu istemiyoruz.

import { useState } from 'react';

let nextId = 0;

export default function List() {
  const [name, setName] = useState('');
  const [artists, setArtists] = useState([]);

  return (
    <>
      <h1>İlham verici heykeltıraşlar:</h1>
      <input
        value={name}
        onChange={e => setName(e.target.value)}
      />
      <button onClick={() => {
        artists.push({
          id: nextId++,
          name: name,
        });
      }}>Ekle</button>
      <ul>
        {artists.map(artist => (
          <li key={artist.id}>{artist.name}</li>
        ))}
      </ul>
    </>
  );
}

Bunun yerine, mevcut öğeleri ve dizinin son elemanı olarak yeni öğeyi içeren yeni diziyi oluşturun. Bunu yapmanın birden çok yolu vardır ancak en kolay yol ... dizi spread sözdizimini kullanmaktır:

setArtists( // State'i yeni bir dizi
[ // ile değiştirin
...artists, // bu eski öğelerin hepsini içerir
{ id: nextId++, name: name } // ve dizinin sonuna eklenecek yeni öğe
]
);

Şimdi doğru şekilde çalışmakta:

import { useState } from 'react';

let nextId = 0;

export default function List() {
  const [name, setName] = useState('');
  const [artists, setArtists] = useState([]);

  return (
    <>
      <h1>İlham verici heykeltıraşlar:</h1>
      <input
        value={name}
        onChange={e => setName(e.target.value)}
      />
      <button onClick={() => {
        setArtists([
          ...artists,
          { id: nextId++, name: name }
        ]);
      }}>Ekle</button>
      <ul>
        {artists.map(artist => (
          <li key={artist.id}>{artist.name}</li>
        ))}
      </ul>
    </>
  );
}

Dizi spread sözdizimi yeni öğeyi orijinal ...artists‘den önceye yerleştirerek dizinin başına eklemenizi de sağlar:

setArtists([
{ id: nextId++, name: name },
...artists // Eski öğeleri dizinin sonuna yerleştir
]);

Bu şekilde, spread sözdizimi push() (öğeyi dizinin sonuna eklemek) ve unshift() (öğeyi dizinin başına eklemek) metodlarının görevini yapabilir. Yukarıdaki sandbox’ta deneyebilirsiniz!

Bir diziden çıkartmak

Diziden bir öğeyi çıkartmanın en kolay yolu o öğeyi filtrelemek’tir. Bir başka deyişle, o öğeyi içermeyen yeni bir dizi oluşturmaktır. Bunu yapmak için filter metodunu kullanabilirsiniz. Örneğin:

import { useState } from 'react';

let initialArtists = [
  { id: 0, name: 'Marta Colvin Andrade' },
  { id: 1, name: 'Lamidi Olonade Fakeye'},
  { id: 2, name: 'Louise Nevelson'},
];

export default function List() {
  const [artists, setArtists] = useState(
    initialArtists
  );

  return (
    <>
      <h1>İlham verici heykeltıraşlar:</h1>
      <ul>
        {artists.map(artist => (
          <li key={artist.id}>
            {artist.name}{' '}
            <button onClick={() => {
              setArtists(
                artists.filter(a =>
                  a.id !== artist.id
                )
              );
            }}>
              Sil
            </button>
          </li>
        ))}
      </ul>
    </>
  );
}

“Sil” butonuna birkaç kez tıklayın ve tıklama yöneticisine bakın.

setArtists(
artists.filter(a => a.id !== artist.id)
);

Burada artists.filter(a => a.id !== artist.id) ifadesi “ID’leri artist.id‘den farklı olan artists‘den oluşan yeni bir dizi oluştur” anlamına gelmektedir. Diğer bir deyişle, her bir artist’e karşılık gelen “Sil” butonu o artist’i diziden filtreleyecek ve nihai dizi ile yeniden render isteği gönderecektir. filter metodunun orijinal diziyi değiştirmediğini unutmayın.

Bir diziyi dönüştürmek

Eğer dizideki bazı ya da tüm öğeleri değiştirmek isterseniz yeni bir dizi oluşturmak için map() metodunu kullanabilirsiniz. map‘e ileteceğiniz fonksiyon, verisine veya indeksine (veya her ikisine) dayalı olarak her bir öğeyle ne yapacağınızı belirler.

Bu örnekte dizi, iki daire ve bir karenin koordinatlarını içermektedir. Butona tıkladığınız zaman sadece daireler 50 piksel aşağı hareket etmektedir. Bunu, map() metodunu kullanıp yeni bir veri dizisi oluşturarak yapar:

import { useState } from 'react';

let initialShapes = [
  { id: 0, type: 'circle', x: 50, y: 100 },
  { id: 1, type: 'square', x: 150, y: 100 },
  { id: 2, type: 'circle', x: 250, y: 100 },
];

export default function ShapeEditor() {
  const [shapes, setShapes] = useState(
    initialShapes
  );

  function handleClick() {
    const nextShapes = shapes.map(shape => {
      if (shape.type === 'square') {
        // Değişiklik yok
        return shape;
      } else {
        // 50 piksel aşağıda yeni bir daire döndürür
        return {
          ...shape,
          y: shape.y + 50,
        };
      }
    });
    // Yeni dizi ile yeniden render et
    setShapes(nextShapes);
  }

  return (
    <>
      <button onClick={handleClick}>
        Daireleri aşağı hareket ettir!
      </button>
      {shapes.map(shape => (
        <div
          key={shape.id}
          style={{
          background: 'purple',
          position: 'absolute',
          left: shape.x,
          top: shape.y,
          borderRadius:
            shape.type === 'circle'
              ? '50%' : '',
          width: 20,
          height: 20,
        }} />
      ))}
    </>
  );
}

Bir dizideki öğeleri değiştirmek

Bir dizideki bir veya daha fazla öğeyi değiştirmek oldukça sık istenmektedir. arr[0] = 'bird' gibi atamalar yapmak orijinal diziyi mutasyona uğrattığı için burada da map metodunu kullanmak mantıklı olacaktır.

Bir öğeyi değiştirmek için map ile yeni bir dizi oluşturun. map metodu içinde, ikinci argüman olarak öğenin indeksini alacaksınız. Bu indeksi orijinal öğeyi (fonksiyonun ilk argümanı) veya başka bir öğeyi döndürüp döndürmeyeceğinize karar vermek için kullanın:

import { useState } from 'react';

let initialCounters = [
  0, 0, 0
];

export default function CounterList() {
  const [counters, setCounters] = useState(
    initialCounters
  );

  function handleIncrementClick(index) {
    const nextCounters = counters.map((c, i) => {
      if (i === index) {
        // Tıklanan sayacı artır
        return c + 1;
      } else {
        // Geri kalan değişmez
        return c;
      }
    });
    setCounters(nextCounters);
  }

  return (
    <ul>
      {counters.map((counter, i) => (
        <li key={i}>
          {counter}
          <button onClick={() => {
            handleIncrementClick(i);
          }}>+1</button>
        </li>
      ))}
    </ul>
  );
}

Dizide belli bir konuma eklemek

Bazen bir öğeyi ne dizinin başına ne de dizinin sonuna değil de belirlediğiniz başka bir konuma eklemek isteyebilirsiniz. Bunu yapmak için, ... dizi spread sözdizimini slice() metodu ile beraber kullanabilirsiniz. slice() metodu diziden bir “dilim (slice)” almanızı sağlar. Yeni öğeyi eklemek için, eklemek istediğiniz konumdan önceki dilimden spread sözdizimi ile yeni bir dizi oluşturacak, ardından yeni öğeyi ekleyecek ve son olarak da orijinal dizinin geri kalanını ekleyeceksiniz.

Bu örnekte, Ekle butonu her zaman 1 indeksinde ekler:

import { useState } from 'react';

let nextId = 3;
const initialArtists = [
  { id: 0, name: 'Marta Colvin Andrade' },
  { id: 1, name: 'Lamidi Olonade Fakeye'},
  { id: 2, name: 'Louise Nevelson'},
];

export default function List() {
  const [name, setName] = useState('');
  const [artists, setArtists] = useState(
    initialArtists
  );

  function handleClick() {
    const insertAt = 1; // Herhangi bir indeks olabilir
    const nextArtists = [
      // Eklemek istediğiniz konumdan önceki öğeler:
      ...artists.slice(0, insertAt),
      // Yeni öğe:
      { id: nextId++, name: name },
      // Eklemek istediğiniz konumdan sonraki öğeler:
      ...artists.slice(insertAt)
    ];
    setArtists(nextArtists);
    setName('');
  }

  return (
    <>
      <h1>İlham verici heykeltıraşlar:</h1>
      <input
        value={name}
        onChange={e => setName(e.target.value)}
      />
      <button onClick={handleClick}>
        Ekle
      </button>
      <ul>
        {artists.map(artist => (
          <li key={artist.id}>{artist.name}</li>
        ))}
      </ul>
    </>
  );
}

Bir dizide başka değişiklikler yapmak

Spread sözdizimi, map() ve filter() metodları gibi diziyi mutasyona uğratmayan yöntemlerle yapamayacağınız bazı şeyler vardır. Örneğin, bir diziyi sıralamak veya dizi öğelerini ters çevirmek isteyebilirsiniz. JavaScript’in reverse() ve sort() metodları orijinal diziyi mutasyona uğrattığından dolayı direkt olarak bu metodları kullanamazsınız.

Ancak, önce diziyi kopyalayabilir ve sonra o dizi üzerinde değişiklikler yapabilirsiniz.

Örneğin:

import { useState } from 'react';

let nextId = 3;
const initialList = [
  { id: 0, title: 'Big Bellies' },
  { id: 1, title: 'Lunar Landscape' },
  { id: 2, title: 'Terracotta Army' },
];

export default function List() {
  const [list, setList] = useState(initialList);

  function handleClick() {
    const nextList = [...list];
    nextList.reverse();
    setList(nextList);
  }

  return (
    <>
      <button onClick={handleClick}>
        Ters Çevir
      </button>
      <ul>
        {list.map(artwork => (
          <li key={artwork.id}>{artwork.title}</li>
        ))}
      </ul>
    </>
  );
}

Burada [...list] spread sözdizimi kullanılarak orijinal dizinin bir kopyası oluşturulur. Artık bir kopyanız olduğuna göre nextList.reverse() ya da nextList.sort() gibi mutasyona sebep olan metodlar kullanabilir, hatta nextList[0] = "something" ile öğeleri tek tek yeni değerlerine atayabilirsiniz.

Ancak, bir diziyi kopyalasanız bile dizinin içindeki öğeleri doğrudan mutasyona uğratamazsınız. Bunun nedeni yaptığınız kopyalamanın yüzeysel (shallow) olmasıdır. Yani yeni dizi, orijinal diziyle aynı öğeleri içermektedir. Dolayısıyla, kopyalanan dizinin içindeki bir nesneyi değiştirdiğiniz zaman mevcut state’i de mutasyona uğratmış olursunuz. Örneğin, aşağıdaki gibi bir kod sorunludur.

const nextList = [...list];
nextList[0].seen = true; // Sorun: list[0]'ı mutasyona uğratır
setList(nextList);

nextList ve list iki farklı dizi olmasına rağmen, nextList[0] ve list[0] ifadeleri aynı nesneyi işaret eder. Yani nextList[0].seen değerini değiştirirseniz, aynı zamanda list[0].seen değerini de değiştirmiş olursunuz. Bu, state’i mutasyona uğratmaktır ki bundan kaçınmalısınız! Bu sorunu iç içe JavaScript nesnelerini güncelleme yöntemine benzer şekilde, değiştirmek istediğiniz öğeleri mutasyona uğratmak yerine tek tek kopyalayarak çözebilirsiniz. Nasıl yapıldığını görelim.

Dizi içindeki nesneleri güncelleme

Nesneler dizilerin gerçekten “içinde” değillerdir. Yazdığınız kodda “içeride” olarak görünebilir ancak bir dizideki her nesne, dizinin “işaret ettiği” ayrı bir değerdir. Bu yüzden list[0] gibi iç içe ifadeleri değiştirirken dikkatli olmalısınız. Başka bir kişinin sanat eseri listesi (artwork list), dizinin aynı öğesine işaret edebilir!

İç içe geçmiş state’i güncellerken, güncellemek istediğiniz noktadan en üst düzeye kadar kopyalar oluşturmanız gerekir. Şimdi bunun nasıl olduğunu görelim.

Bu örnekte, iki farklı sanat eseri listesi aynı ilk state’e (initialList) sahiptir. Bu listelerin izole olmaları gerekirdi ancak bir mutasyon nedeniyle yanlışlıkla state’leri paylaşmaktadırlar ve listedeki bir kutuyu işaretlemek diğer listedeki kutuları da etkilemektedir:

import { useState } from 'react';

let nextId = 3;
const initialList = [
  { id: 0, title: 'Big Bellies', seen: false },
  { id: 1, title: 'Lunar Landscape', seen: false },
  { id: 2, title: 'Terracotta Army', seen: true },
];

export default function BucketList() {
  const [myList, setMyList] = useState(initialList);
  const [yourList, setYourList] = useState(
    initialList
  );

  function handleToggleMyList(artworkId, nextSeen) {
    const myNextList = [...myList];
    const artwork = myNextList.find(
      a => a.id === artworkId
    );
    artwork.seen = nextSeen;
    setMyList(myNextList);
  }

  function handleToggleYourList(artworkId, nextSeen) {
    const yourNextList = [...yourList];
    const artwork = yourNextList.find(
      a => a.id === artworkId
    );
    artwork.seen = nextSeen;
    setYourList(yourNextList);
  }

  return (
    <>
      <h1>Görülecek Sanat Eserleri Listesi</h1>
      <h2>Görmek istediğim eserler listesi:</h2>
      <ItemList
        artworks={myList}
        onToggle={handleToggleMyList} />
      <h2>Senin görmek istediğin eserler listesi:</h2>
      <ItemList
        artworks={yourList}
        onToggle={handleToggleYourList} />
    </>
  );
}

function ItemList({ artworks, onToggle }) {
  return (
    <ul>
      {artworks.map(artwork => (
        <li key={artwork.id}>
          <label>
            <input
              type="checkbox"
              checked={artwork.seen}
              onChange={e => {
                onToggle(
                  artwork.id,
                  e.target.checked
                );
              }}
            />
            {artwork.title}
          </label>
        </li>
      ))}
    </ul>
  );
}

Bu koddaki sorun şudur:

const myNextList = [...myList];
const artwork = myNextList.find(a => a.id === artworkId);
artwork.seen = nextSeen; // Sorun: mevcut öğeyi mutasyona uğratır
setMyList(myNextList);

myNextList dizisi yeni bir dizi olmasına rağmen, dizi içindeki öğeler orijinal myList dizisindeki öğeler ile aynıdır. Yani artwork.seen‘i değiştirmek orijinal sanat eserini de değiştirir. Bu sanat eseri yourList dizisinde de olduğu için hata burdan kaynaklanmaktadır. Bunun gibi hataları düşünmek zor olabilir, ancak state’i mutasyona uğratmaktan kaçınırsanız bu hatalar ortadan kalkacaktır.

Eski bir öğeyi mutasyon olmadan güncellenmiş sürümüyle değiştirmek için map metodunu kullanabilirsiniz.

setMyList(myList.map(artwork => {
if (artwork.id === artworkId) {
// Değişikliklerle *yeni* bir nesne oluştur
return { ...artwork, seen: nextSeen };
} else {
// Değişiklik yok
return artwork;
}
}));

Burada ..., bir nesnenin kopyasını oluşturmak için kullanılan nesne spread sözdizimidir.

Bu yaklaşımla, mevcut state öğelerinin hiçbiri mutasyona uğramamış olur ve hata düzeltilir:

import { useState } from 'react';

let nextId = 3;
const initialList = [
  { id: 0, title: 'Big Bellies', seen: false },
  { id: 1, title: 'Lunar Landscape', seen: false },
  { id: 2, title: 'Terracotta Army', seen: true },
];

export default function BucketList() {
  const [myList, setMyList] = useState(initialList);
  const [yourList, setYourList] = useState(
    initialList
  );

  function handleToggleMyList(artworkId, nextSeen) {
    setMyList(myList.map(artwork => {
      if (artwork.id === artworkId) {
        // Değişikliklerle *yeni* bir nesne oluştur
        return { ...artwork, seen: nextSeen };
      } else {
        // Değişiklik yok
        return artwork;
      }
    }));
  }

  function handleToggleYourList(artworkId, nextSeen) {
    setYourList(yourList.map(artwork => {
      if (artwork.id === artworkId) {
        // Değişikliklerle *yeni* bir nesne oluştur
        return { ...artwork, seen: nextSeen };
      } else {
        // Değişiklik yok
        return artwork;
      }
    }));
  }

  return (
    <>
      <h1>Görülecek Sanat Eserleri Listesi</h1>
      <h2>Görmek istediğim eserler listesi:</h2>
      <ItemList
        artworks={myList}
        onToggle={handleToggleMyList} />
      <h2>Senin görmek istediğin eserler listesi:</h2>
      <ItemList
        artworks={yourList}
        onToggle={handleToggleYourList} />
    </>
  );
}

function ItemList({ artworks, onToggle }) {
  return (
    <ul>
      {artworks.map(artwork => (
        <li key={artwork.id}>
          <label>
            <input
              type="checkbox"
              checked={artwork.seen}
              onChange={e => {
                onToggle(
                  artwork.id,
                  e.target.checked
                );
              }}
            />
            {artwork.title}
          </label>
        </li>
      ))}
    </ul>
  );
}

Genel olarak, yalnızca az önce oluşturduğunuz nesneleri mutasyona uğratmalısınız. Yeni bir sanat eseri ekliyorsanız, onu mutasyona uğratabilirsiniz, ancak zaten state’te olan bir eserde bir değişiklik yapıyorsanız, bir kopya oluşturmanız gerekmektedir.

Immer kullanarak kısa ve öz güncelleme mantığı yazmak

İç içe dizileri mutasyona uğratmadan güncellemek tıpkı nesnelerde olduğu gibi biraz tekrara binebilir:

  • Genel olarak, state’i birkaç seviyeden daha derine güncellemeniz gerekmez. Ancak state nesneleriniz çok derinse, düz (flat) olmaları için onları farklı şekilde yeniden yapılandırmak isteyebilirsiniz.
  • Eğer state yapınızı değiştirmek istemiyorsanız, Immer kullanmak isteyebilirsiniz. Immer, diziyi mutasyona uğratacak sözdizimlerini kullanmanıza izin vererek, kopyalama işlemlerini sizin yerinize kendisi yapar.

Immer ile yazılmış örneği aşağıda görebilirsiniz:

import { useState } from 'react';
import { useImmer } from 'use-immer';

let nextId = 3;
const initialList = [
  { id: 0, title: 'Big Bellies', seen: false },
  { id: 1, title: 'Lunar Landscape', seen: false },
  { id: 2, title: 'Terracotta Army', seen: true },
];

export default function BucketList() {
  const [myList, updateMyList] = useImmer(
    initialList
  );
  const [yourList, updateYourList] = useImmer(
    initialList
  );

  function handleToggleMyList(id, nextSeen) {
    updateMyList(draft => {
      const artwork = draft.find(a =>
        a.id === id
      );
      artwork.seen = nextSeen;
    });
  }

  function handleToggleYourList(artworkId, nextSeen) {
    updateYourList(draft => {
      const artwork = draft.find(a =>
        a.id === artworkId
      );
      artwork.seen = nextSeen;
    });
  }

  return (
    <>
      <h1>Görülecek Sanat Eserleri Listesi</h1>
      <h2>Görmek istediğim eserler listesi:</h2>
      <ItemList
        artworks={myList}
        onToggle={handleToggleMyList} />
      <h2>Senin görmek istediğin eserler listesi:</h2>
      <ItemList
        artworks={yourList}
        onToggle={handleToggleYourList} />
    </>
  );
}

function ItemList({ artworks, onToggle }) {
  return (
    <ul>
      {artworks.map(artwork => (
        <li key={artwork.id}>
          <label>
            <input
              type="checkbox"
              checked={artwork.seen}
              onChange={e => {
                onToggle(
                  artwork.id,
                  e.target.checked
                );
              }}
            />
            {artwork.title}
          </label>
        </li>
      ))}
    </ul>
  );
}

Immer ile artwork.seen = nextSeen gibi mutasyonların artık sorun çıkarmadığına dikkat edin:

updateMyTodos(draft => {
const artwork = draft.find(a => a.id === artworkId);
artwork.seen = nextSeen;
});

Bunun nedeni, orijinal state’i mutasyona uğratmamanızdır. Burada Immer tarafından sağlanan özel bir draft nesnesini mutasyona uğratmaktayız. Benzer şekilde, draft nesnesine push() ve pop() gibi mutasyona neden olan metodları da uygulayabilirsiniz.

Arka planda Immer, draft‘a yaptığınız değişikliklere göre her zaman bir sonraki state’i sıfırdan oluşturur. Bu, olay yönetecilerinizi, state’i hiç mutasyona uğratmadan kısa ve öz olarak tutar.

Özet

  • State’e dizi koyabilirsiniz ancak değiştiremezsiniz.
  • Bir diziyi mutasyona uğratmak yerine o dizinin yeni bir sürümünü oluşturun ve state’i buna göre güncelleyin.
  • [...arr, newItem] dizi spread sözdizimini kullanarak yeni öğelerle bir dizi oluşturabilirsiniz
  • filter() ve map() metodlarını kullanarak filtrelenmiş ya da dönüştürülmüş yeni diziler oluşturabilirsiniz.
  • Kodunuzu kısa ve öz tutmak için Immer’ı kullanabilirsiniz.

Problem 1 / 4:
Alışveriş sepetindeki ürünü güncelleyin

handleIncreaseClick fonksiyonunun mantığını yazın ki ”+” butonuna tıklandığında ürünün sepetteki sayısı artsın:

import { useState } from 'react';

const initialProducts = [{
  id: 0,
  name: 'Baklava',
  count: 1,
}, {
  id: 1,
  name: 'Cheese',
  count: 5,
}, {
  id: 2,
  name: 'Spaghetti',
  count: 2,
}];

export default function ShoppingCart() {
  const [
    products,
    setProducts
  ] = useState(initialProducts)

  function handleIncreaseClick(productId) {

  }

  return (
    <ul>
      {products.map(product => (
        <li key={product.id}>
          {product.name}
          {' '}
          (<b>{product.count}</b>)
          <button onClick={() => {
            handleIncreaseClick(product.id);
          }}>
            +
          </button>
        </li>
      ))}
    </ul>
  );
}