Как реплицировать компоненты на основе классов asyn c setState метод с реакцией - PullRequest
0 голосов
/ 20 марта 2020

Я хочу обновить состояние для каждого элемента массива. Но после выполнения функции в состоянии находится только последний элемент массива?

В компоненте на основе классов мы используем метод обратного вызова с функцией setstate для выполнения любого действия с обновленным состоянием. Как это сделать на крючке?

import React, { useState, useEffect, useRef } from "react";


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

const add = ({name, value}) => {
  setState( [...state, {name, value}]);
}

useEffect(() => {
  console.log('update')
}, [state])

const handleClick = () => {
const array = [{
  name: 'Sam',
  value: '23'
},{
  name: 'Ram',
  value: '24'
},{
  name: 'Pam',
  value: '25'
}]
for(const a of array){
  console.log({a})
  add(a);
  }
}
return (
  <div className="App">
    <button onClick={handleClick}>add</button>
  </div>
 );
}

1 Ответ

3 голосов
/ 20 марта 2020

Обновления состояний асинхронные. Повторно делая

setState( [...state, {name, value}]);

, вы несколько раз используете оригинальный state, а не новый.

В идеале, не вызывайте setState несколько раз, не позволяя компоненту сделайте перерыв между ними, сделайте что-то вроде этого:

const addAll = (entries) => {
  setState([...state, ...entries]);
};

addAll(array);

Но если вам нужно повторно вызывать свой установщик состояний, используйте форму обратного вызова, чтобы вы всегда использовали текущее состояние, а не устаревшее состояние :

setState(currentState => [...currentState, {name, value}]);

В комментарии вы сказали:

setState(currentState => ({...currentState, [name]: value})) Но для объекта это не работает

Это делает этот код выглядит совершенно правильно, если вы пытаетесь установить свойство, имя которого в name, равно value:

const { useState } = React;

const Example = () => {
    const [state, setState] = useState({
        a: 1,
        b: 2
    });
    
    const updateProperty = (name, value) => {
        setState(currentState => ({...currentState, [name]: value}));
    };
    
    const addA = () => {
        updateProperty("a", state.a + 1);
    };
    
    const addB = () => {
        updateProperty("b", state.b + 1);
    };
    
    const addC = () => {
        updateProperty("c", (state.c || 0) + 1);
    };
    
    return (
        <div>
            <div>a = {state.a}, b = {state.b}, c = {state.c}</div>
            <input type="button" value="Inc A" onClick={addA} />
            <input type="button" value="Inc B" onClick={addB} />
            <input type="button" value="Create/Inc C" onClick={addC} />
        </div>
    );
};

ReactDOM.render(<Example />, document.getElementById("root"));
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.12.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.12.0/umd/react-dom.production.min.js"></script>

Однако я не рекомендую это делать. С помощью крючков лучше хранить данные о состоянии отдельно:

const { useState } = React;

const Example = () => {
    const [a, setA] = useState(1);
    const [b, setB] = useState(2);
    const [c, setC] = useState(undefined);
    
    const addA = () => {
        setA(a => a + 1);
    };
    
    const addB = () => {
        setB(b => b + 1);
    };
    
    const addC = () => {
        setC(c => (c || 0) + 1);
    };
    
    return (
        <div>
            <div>a = {a}, b = {b}, c = {c}</div>
            <input type="button" value="Inc A" onClick={addA} />
            <input type="button" value="Inc B" onClick={addB} />
            <input type="button" value="Create/Inc C" onClick={addC} />
        </div>
    );
};

ReactDOM.render(<Example />, document.getElementById("root"));
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.12.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.12.0/umd/react-dom.production.min.js"></script>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...