如何在React中使用钩子从父组件获取其值的父组件中更新正确的状态值?

时间:2019-10-14 21:50:46

标签: reactjs state react-hooks

我正在做一个反应项目,并且对使用当前正确的状态值有疑问。我已经在一个小的虚拟项目中重新创建了该问题,该项目包含一个父组件和一个子组件。 Child从Parent组件传递到props,一个状态变量和一个使用反应挂钩(useState)更新所述状态的函数。在驻留在Parent组件中的原始函数中,是对第二个函数的调用,该第二个函数根据当前状态执行操作。我的控制台日志和结果表明,传递的函数会发送回正确的值以进行更新,但是以下函数未使用更新后的值,而是似乎始终落后于一个渲染器。

我尝试使用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,因此显示“ apple”而不是“ cherry”。感谢所有帮助/建议,谢谢!

1 个答案:

答案 0 :(得分:0)

反应状态更新操作是异步的,并且为提高性能而进行了批处理。不能保证console.log('state of count in second method', count);会反映出更新后的状态。

解决方案1:使用传入的index中的secondMethod值作为参数

解决方案2:使用fruit钩子更新{strong} 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] }));
};