Metoda Push w Hookach Reacta (useState)?

Jak wcisnąć element wewnątrz tablicy useState reactowego Hooka? Czy to stara metoda w stanie Reacta? Czy coś nowego?

Np. setState push example ?

Author: skyboyer, 2019-02-13

9 answers

Kiedy używasz useState, można uzyskać metodę aktualizacji dla elementu state:

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

Następnie, gdy chcesz dodać nowy element, używasz tej funkcji i przekazujesz nową tablicę lub funkcję, która utworzy nową tablicę. Zwykle ten ostatni, ponieważ aktualizacje stanu są asynchroniczne i czasami wsadowe:

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

Czasami możesz uciec bez użycia tego formularza zwrotnego, jeśli tylko zaktualizujesz tablicę w programach obsługi dla określonych zdarzeń użytkownika, takich jak click (ale nie jak mousemove):

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

Zdarzenia, dla których React zapewnia wyrównanie renderowania, są "dyskretnymi zdarzeniami" wymienionymi tutaj .

Live Example (przekazywanie wywołania zwrotnego do setTheArray):

const {useState, useCallback} = React;
function Example() {
    const [theArray, setTheArray] = useState([]);
    const addEntryClick = () => {
        setTheArray(oldArray => [...oldArray, `Entry ${oldArray.length}`]);
    };
    return [
        <input type="button" onClick={addEntryClick} value="Add" />,
        <div>{theArray.map(entry =>
          <div>{entry}</div>
        )}
        </div>
    ];
}

ReactDOM.render(
    <Example />,
    document.getElementById("root")
);
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.1/umd/react-dom.production.min.js"></script>
Ponieważ jedyną aktualizacją do theArray jest ta w zdarzeniu click (jednym z "dyskretnych" zdarzeń), mogłem uniknąć bezpośredniej aktualizacji w addEntry:

const {useState, useCallback} = React;
function Example() {
    const [theArray, setTheArray] = useState([]);
    const addEntryClick = () => {
        setTheArray([...theArray, `Entry ${theArray.length}`]);
    };
    return [
        <input type="button" onClick={addEntryClick} value="Add" />,
        <div>{theArray.map(entry =>
          <div>{entry}</div>
        )}
        </div>
    ];
}

ReactDOM.render(
    <Example />,
    document.getElementById("root")
);
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.1/umd/react-dom.production.min.js"></script>
 336
Author: T.J. Crowder,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-12-27 09:02:31

Aby rozwinąć nieco dalej, oto kilka typowych przykładów. Zaczynając od:

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

Element Push na końcu tablicy

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

Push / update element na końcu obiektu

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

Push / update element na końcu tablicy obiektów

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

Element Push na końcu obiektu tablic

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

Oto kilka przykładów roboczych. https://codesandbox.io/s/reacthooks-push-r991u

 54
Author: Elia Ahadi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-06-05 16:13:49

Tak samo jak robisz to ze stanem" normalnym " w komponentach klasy Reactowej.

Przykład:

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>
  );
}
 5
Author: r g,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-02-13 18:28:46
// 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

 3
Author: Adarsh Pawar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-05-13 18:20:36

setTheArray([...theArray, newElement]); jest najprostszą odpowiedzią, ale należy uważać na mutację przedmiotów w theArray . Użyj głębokiego klonowania elementów tablicy.

 2
Author: Shivang Gupta,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-12-13 05:20:18

Możesz dołączyć tablicę danych na końcu stanu niestandardowego:

  const [vehicleData, setVehicleData] = React.useState<any[]>([]);
  setVehicleData(old => [...old, ...newArrayData]);

Na przykład, poniżej, pojawi się przykład axios:

  useEffect(() => {
    const fetchData = async () => {
      const result = await axios(
        {
          url: `http://localhost:4000/api/vehicle?page=${page + 1}&pageSize=10`,
          method: 'get',
        }
      );
      setVehicleData(old => [...old, ...result.data.data]);
    };

    fetchData();
  }, [page]);
 2
Author: Mohammad Fallah,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-12-22 17:25:12

Najbardziej zalecaną metodą jest użycie funkcji wrapper i operatora spread razem. Na przykład, jeśli zainicjowałeś Stan o nazwie name w ten sposób,

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

Możesz wcisnąć do tej tablicy w ten sposób,

setNames(names => [...names, newName])
Mam nadzieję, że to pomoże.
 1
Author: Khondoker Zahidul Hossain,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-06-10 06:40:10

Jeśli chcesz wcisnąć po konkretnym indeksie, możesz zrobić to jak poniżej:

   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;
        });
    };
 1
Author: Hossein Haji Mali,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-11-16 14:00:43

Wypróbowałem powyższe metody do wpychania obiektu do tablicy obiektów w useState, ale wystąpił następujący błąd podczas używania TypeScript :

Type ' txbacklog[] | undefined 'must have a' Symbol.iterator ' metoda, która zwraca iterator.ts (2488)

Konfiguracja dla tsconfig.JSON miał chyba rację:

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

To obejście rozwiązało problem (mój przykładowy kod):

Interfejs:

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

Zmienna stanu:

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

Push new object do tablicy:

    // 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
Author: Sergi Juanati,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-11-14 18:17:47