Push-Methode in React Hooks (useState)?


Antworten:


270

Wenn Sie verwenden useState, können Sie eine Aktualisierungsmethode für das Statuselement erhalten:

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

Wenn Sie dann ein neues Element hinzufügen möchten, verwenden Sie diese Funktion und übergeben das neue Array oder eine Funktion, die das neue Array erstellt. Normalerweise letzteres, da Statusaktualisierungen asynchron und manchmal stapelweise sind:

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

Manchmal kann man , ohne dass die Callback - Formular weg, wenn Sie nur das Array in Handler für bestimmte Benutzerereignisse aktualisieren wie click(aber nicht wie mousemove):

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

Die Ereignisse , für die gewährleistet , dass Reagieren Rendering gespült wird die „diskrete Ereignisse“ aufgeführt hier .

Live-Beispiel (Rückruf an setTheArray):

Da das einzige Update darin theArraydas in einem clickEreignis ist (eines der "diskreten" Ereignisse), könnte ich mit einem direkten Update davonkommen addEntry:


1
... und versuchen Sie es, setTheArray(currentArray => [...currentArray, newElement])wenn das oben genannte nicht funktioniert. Höchstwahrscheinlich useEffect(...theArray..., [])ist es wichtig zu erkennen, dass dies theArrayeine Konstante ist, daher sind funktionale Aktualisierungen für Werte aus zukünftigen
Renderings

@Aprillion - Nicht ganz sicher, was Sie mit diesem useEffectBeispiel sagen ...?
TJ Crowder

1
Wenn das useEffecteine leere Abhängigkeitsliste hat [], wird es nur beim ersten Rendern ausgeführt. Der Wert von theArrayinnerhalb des Effekts wird also immer sein initialArray. In Situationen, in denen setTheArray([...initialArray, newElement])dies keinen Sinn theArrayergibt und in denen die Konstante immer gleich ist, initialValuesind Funktionsaktualisierungen erforderlich.
Aprillion

@Aprillion - Ich fürchte, ich verstehe es immer noch nicht, möglicherweise ein bisschen dicht. :-) Warum brauchen Sie einen Effekt nur mit dem anfänglichen Array-Wert? (Ich meine, es mag einen seltenen Anwendungsfall geben, aber ...) Und selbst wenn Sie dies tun, was hat das mit der Frage zu tun?
TJ Crowder

Hey @TJCrowder, bin ich den Rückruf Art und Weise verwenden , um alte Daten mit neuen zu fusionieren , wenn Daten zu holen, aber aus irgendeinem Grund funktioniert es nicht richtig gut, können Sie überprüfen Sie bitte , dies mein Problem zu verstehen?
Oliver D

46

Um ein wenig weiter zu expandieren, hier einige allgemeine Beispiele. Beginnen mit:

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

Schieben Sie das Element am Ende des Arrays

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

Element am Ende des Objekts pushen / aktualisieren

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

Push / Update-Element am Ende des Array von Objekten

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

Schieben Sie das Element am Ende des Objekts der Arrays

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

Hier sind auch einige Arbeitsbeispiele. https://codesandbox.io/s/reacthooks-push-r991u


4
Vielen Dank für alle Beispiele. Das genaue Problem, mit dem ich ein Problem hatte, war Ihr Push-Element am Ende des Objekts von Arrays . Ich habe so viele verschiedene Dinge ausprobiert, konnte es aber einfach nicht zusammenschustern.
Verdoppeln Sie den

5

Genauso wie Sie es mit dem "normalen" Status in React-Klassenkomponenten tun.

Beispiel:

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>
  );
}

Dies wird mit onClick funktionieren, aber der setState (oldState => [... oldState, pushsomething]) ist, wie Sie es tun sollten
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]);ist die einfachste Antwort, aber achten Sie auf die Mutation von Elementen im Array . Verwenden Sie das Deep Cloning von Array-Elementen.


Das tiefe Klonen, das Sie erwähnen, bedeutet, als objA zu empfangen. UseState und concat das objA mit objB? Gleich wie dieser Link? gist.githubusercontent.com/kahsing/…
Luiey

1

Die am meisten empfohlene Methode ist die gemeinsame Verwendung der Wrapper-Funktion und des Spread-Operators. Wenn Sie beispielsweise einen Status namewie diesen initialisiert haben ,

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

Sie können auf dieses Array wie folgt pushen:

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

Hoffentlich hilft das.


Bitte posten Sie keine Nur-Link-Antworten. Die Verbindung könnte in Zukunft unterbrochen werden. Erstellen Sie stattdessen eine Beschreibung dieses Artikels und stellen Sie sicher, dass Sie die Frage tatsächlich beantworten.
BlackCetha

Während dieser Link die Frage beantworten kann, ist es besser, die wesentlichen Teile der Antwort hier aufzunehmen und den Link als Referenz bereitzustellen. Nur-Link-Antworten können ungültig werden, wenn sich die verknüpfte Seite ändert. - Aus der Rezension
ilke444

0

Ich habe die oben genannten Methoden zum Verschieben eines Objekts in ein Array von Objekten in useState ausprobiert, hatte jedoch den folgenden Fehler bei der Verwendung von TypeScript :

Geben Sie 'TxBacklog [] | ein undefined 'muss eine' Symbol.iterator'-Methode haben, die eine iterator.ts (2488) zurückgibt.

Das Setup für tsconfig.json war anscheinend richtig:

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

Diese Problemumgehung hat das Problem gelöst (mein Beispielcode):

Schnittstelle:

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

Zustandsvariable:

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

Neues Objekt in Array schieben:

    // 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

Wenn Sie nach einem bestimmten Index pushen möchten, können Sie wie folgt vorgehen:

   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;
        });
    };
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.