React Hooks'ta (useState) itme yöntemi?


Yanıtlar:


270

Kullandığınızda useState, durum öğesi için bir güncelleme yöntemi alabilirsiniz:

const [theArray, setTheArray] = useState(initialArray);

sonra, yeni bir öğe eklemek istediğinizde, bu işlevi kullanır ve yeni diziyi veya yeni diziyi yaratacak bir işlevi iletirsiniz. Durum güncellemeleri eşzamansız olduğundan ve bazen toplu işlendiğinden, normalde ikincisi:

setTheArray(oldArray => [...oldArray, newElement]);

Bazen , işleyicilerdeki diziyi yalnızca aşağıdakiler gibi click(ancak beğenmeyeceğiniz mousemove) belirli belirli kullanıcı olayları için güncellerseniz , bu geri arama formunu kullanmadan kurtulabilirsiniz :

setTheArray([...theArray, newElement]);

React'in oluşturmanın temizlendiğinden emin olduğu olaylar, burada listelenen "ayrı olaylar" dır .

Canlı Örnek (geri aramayı şuraya iletme setTheArray):

theArrayBuradaki tek güncelleme, clickolaydaki bir güncelleme olduğu için ("ayrı" olaylardan biri), şu konularda doğrudan güncelleme yapabilirim addEntry:


1
... ve setTheArray(currentArray => [...currentArray, newElement])yukarıdakilerin işe yaramazsa deneyin . Büyük olasılıkla useEffect(...theArray..., []), bunun theArraysürekli olduğunu anlamak önemlidir , bu nedenle gelecekteki
— renderlardan

@Aprillion - Bu örnekle ne söylediğinden tam olarak emin değilim useEffect...?
— TJ Crowder

1
Eğer useEffectboş bir bağımlılık listesi vardır [], bu sadece ilk işlemek sırasında çalıştırılacaktır. Yani theArrayetkinin iç değeri her zaman olacaktır initialArray. Durumlarda setTheArray([...initialArray, newElement])anlamlı olmaz ve ne zaman theArraysabiti her zaman eşit olacaktır initialValue, daha sonra fonksiyonel güncelleştirme gerekmektedir.
— Nisan 9'19

@Aprillion - Korkarım hala anlamıyorum, muhtemelen biraz yoğun. :-) Neden sadece ilk dizi değerine sahip bir etkiye ihtiyacınız var ? (Yani, sık olmayan bir kullanım durumu olabilir, ama ...) Ve yapsanız bile, bunun soruyla ne alakası var?
— TJ Crowder

Hey @TJCrowder, ben verileriniz getirilirken yeni ile eski verileri birleştirmek için geri arama yolunu kullanmak değilim, ama nedense bunu kontrol edin edebilirsiniz düzgün iyi çalışmaz oluyor bu benim sorunu anlamak için?
— Oliver D

46

Biraz daha genişletmek için işte bazı yaygın örnekler. Şununla başlayarak:

const [theArray, setTheArray] = useState(initialArray);
const [theObject, setTheObject] = useState(initialObject);

Dizinin sonundaki öğeyi itin

setTheArray(prevArray => [...prevArray, newValue])

Nesnenin sonundaki öğeyi it / güncelle

setTheObject(prevState => ({ ...prevState, currentOrNewKey: newValue}));

Nesne dizisinin sonundaki öğeyi it / güncelle

setTheArray(prevState => [...prevState, {currentOrNewKey: newValue}]);

Dizi nesnesinin sonundaki öğeyi itin

let specificArrayInObject = theObject.array.slice();
specificArrayInObject.push(newValue);
const newObj = { ...theObject, [event.target.name]: specificArrayInObject };
theObject(newObj);

İşte bazı çalışma örnekleri de. https://codesandbox.io/s/reacthooks-push-r991u


4
Tüm örnekler için teşekkür ederim. Sorun yaşadığım şey tam olarak dizi nesnesinin sonundaki Push öğenizdi . Çok farklı şeyler denedim ama bir araya getiremedim.
— sdouble

5

Aynı React sınıfı bileşenlerde "normal" durumla yaptığınız gibi.

misal:

function App() {
  const [state, setState] = useState([]);

  return (
    <div>
      <p>You clicked {state.join(" and ")}</p>
      //destructuring
      <button onClick={() => setState([...state, "again"])}>Click me</button>
      //old way
      <button onClick={() => setState(state.concat("again"))}>Click me</button>
    </div>
  );
}

bu, onClick ile çalışacaktır, ancak setState (oldState => [... oldState, pushsomething]) bunu nasıl yapmanız gerektiğidir
— Cyrus Zei

3
// Save search term state to React Hooks with spread operator and wrapper function

// Using .concat(), no wrapper function (not recommended)
setSearches(searches.concat(query))

// Using .concat(), wrapper function (recommended)
setSearches(searches => searches.concat(query))

// Spread operator, no wrapper function (not recommended)
setSearches([...searches, query])

// Spread operator, wrapper function (recommended)
setSearches(searches => [...searches, query])

https://medium.com/javascript-in-plain-english/how-to-add-to-an-array-in-react-state-3d08ddb2e1dc


2

setTheArray([...theArray, newElement]);en basit cevaptır, ancak Dizideki öğelerin değişmesine dikkat edin . Dizi öğelerinin derinlemesine klonlanmasını kullanın.


Bahsettiğiniz derin klonlama, objA olarak almak anlamına mı geliyor? UseState ve objA'yı objB ile birleştirmek? Bu bağlantıyla aynı mı? gist.githubusercontent.com/kahsing/…
— Luiey

1

En çok önerilen yöntem, sarmalayıcı işlevi ve yayma işlecini birlikte kullanmaktır. Örneğin, böyle bir durumu başlattıysanız name,

const [names, setNames] = useState([])

Bu diziye şu şekilde basabilirsiniz,

setNames(names => [...names, newName])

Umarım yardımcı olur.


Lütfen yalnızca bağlantı içeren yanıtlar göndermeyin. Bağlantı gelecekte kopabilir. Bunun yerine, o makalenin bir yazısını oluşturun ve soruyu gerçekten cevapladığınızdan emin olun.
— BlackCetha

Bu bağlantı soruyu cevaplayabilirken, cevabın temel kısımlarını buraya eklemek ve referans için bağlantıyı sağlamak daha iyidir. Bağlantılı sayfa değişirse yalnızca bağlantı yanıtları geçersiz hale gelebilir. - Yorumdan
— ilke444

0

Bir nesneyi useState'teki bir nesne dizisine itmek için yukarıdaki yöntemleri denedim, ancak TypeScript kullanırken şu hatayı aldım :

'TxBacklog [] yazın | undefined ', yineleyici.ts (2488) döndüren' Symbol.iterator 'yöntemine sahip olmalıdır

Tsconfig.json için kurulum görünüşe göre doğruydu:

{
   "compilerOptions": {
   "target": "es6",
   "lib": [
      "dom",
      "dom.iterable",
      "esnext",
      "es6",
],

Bu geçici çözüm sorunu çözdü (örnek kodum):

Arayüz:

   interface TxBacklog {
      status: string,
      txHash: string,
   }

Durum değişkeni:

    const [txBacklog, setTxBacklog] = React.useState<TxBacklog[]>();

Yeni nesneyi diziye itin:

    // Define new object to be added
    const newTx = {
       txHash: '0x368eb7269eb88ba86..',
       status: 'pending'
    };
    // Push new object into array
    (txBacklog) 
       ? setTxBacklog(prevState => [ ...prevState!, newTx ])
       : setTxBacklog([newTx]);

0

belirli bir dizinden sonra itmek istiyorsanız, aşağıdaki işlemleri yapabilirsiniz:

   const handleAddAfterIndex = index => {
       setTheArray(oldItems => {
            const copyItems = [...oldItems];
            const finalItems = [];
            for (let i = 0; i < copyItems.length; i += 1) {
                if (i === index) {
                    finalItems.push(copyItems[i]);
                    finalItems.push(newItem);
                } else {
                    finalItems.push(copyItems[i]);
                }
            }
            return finalItems;
        });
    };
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.