Как обновить правильное значение состояния в родительском компоненте, который получает свое значение от дочернего компонента, используя ловушки в реакции? - PullRequest
2 голосов
/ 15 октября 2019

Я работаю над реактивным проектом, и у меня возникла проблема с использованием текущего правильного значения состояния. Я воссоздал проблему в небольшом фиктивном проекте, который содержит родительский компонент и дочерний компонент. Дочерний объект передается через реквизиты из родительского компонента, одну переменную состояния и одну функцию, которая обновляет указанное состояние с использованием активных перехватчиков (useState). В исходной функции, находящейся в родительском компоненте, есть вызов второй функции, которая выполняет действие на основе текущего состояния. У меня есть консольные журналы и результаты, показывающие, что переданная функция отправляет обратно правильное значение для обновления, но следующая функция не использует обновленное значение, вместо этого, кажется, всегда отстает на один рендер.

Я пытался использовать async / await, а также ловушку useEffect. Я смог получить «ожидаемый» результат, используя некоторую вариацию useEffect в этом небольшом фиктивном проекте, однако он не превратился в реальный дуэт проекта, так как их было больше вызовов функций, которые также зависят от значения состояния, хотя я могупросто не поймите / сделайте что-то не так.

export const Parent = () => {

    const [count, setCount] = useState(0);
    const [fruit, setFruit] = useState(null);

    const counter = (index) => {
        console.log("index passed in: ", index);
        setCount(index);
        secondMethod()
    }

    const secondMethod = () => {
        console.log('state of count in second method', count);
        const arr = ['apple', 'cherry', 'orange', 'kiwi', 'berry'];
        setFruit(arr[count]);
    }

    return (
        <div>
            <p>Hello from Parent, current count: {count}</p>
            <Child counter={counter} count={count}/>
            <p>result of second method: {fruit}</p>
        </div>
    );
}

export const Child = ({ counter, count }) => {
    return (
        <div>
            <p>Child comp</p>
            <button onClick={() => counter(count + 1)}>
                Click on send counter
            </button>
        </div>
    );
}

Значение лога консоли в индексе верное, а также вывод {count}. Результат консольного журнала от secondMethod и, следовательно, состояние setFruit неверно и использует состояние от одного рендера позади? Таким образом, count будет отображаться как 1, но secondMethod по-прежнему будет иметь значение count в качестве значения 0, поэтому вместо «cherry» отображается «apple». Я ценю любую помощь и предложения, спасибо!

1 Ответ

0 голосов
/ 15 октября 2019

Действие обновлений состояния реакции является асинхронным и пакетируется для повышения производительности. Нет гарантии, что console.log('state of count in second method', count); будет отражать обновленное состояние.

Решение 1: использовать значение index в secondMethod, переданное в качестве параметра

Решение 2: обновите fruit после обновления count с помощью ловушки useEffect. Замените secondMethod на:

useEffect(() => {
    console.log('state of count in useEffect', count);
    const arr = ['apple', 'cherry', 'orange', 'kiwi', 'berry'];
    setFruit(arr[count]);
}, [count, setFruit]);

Решение 3: Если ваши состояния сильно зависят друг от друга, то, возможно, они должны быть частью одного и того же состояния. Таким образом, вы можете использовать версию функции setState, которая всегда получает правильное предыдущее значение.

// join separate states together
const [fruitCount, setFruitCount] = useState({ count: 0, fruit: null });

const counter = index => {
    setFruitCount({ count: index });
    secondMethod();
};

const secondMethod = () => {
    const arr = ["apple", "cherry", "orange", "kiwi", "berry"];
    // use setState function, count is taken from the previous state value
    setFruitCount(prevState => ({ ...prevState, fruit: arr[prevState.count] }));
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...