gpt4 book ai didi

ReactJS 上下文 > 从状态函数引用最新状态值

转载 作者:行者123 更新时间:2023-12-05 06:22:39 27 4
gpt4 key购买 nike

我目前正在使用我见过的常见 Context 模式,它允许子组件通过传递修饰函数来更新父组件的状态(即 Provider)通过共享的 Context

我遇到的问题是,修改函数只引用原始状态,不引用最新状态...

有没有办法从修饰函数(即modUser)获取最新的状态值(即state.user)?

下面是要重现的最少代码:

预期输出: Nick ...然后是 Bob ...然后是 BOB

实际输出: Nick ...然后是 Bob ...然后是 NICK

import React, { useState, useContext, useEffect } from "react"

const defaultState = {
user: null,
setUser: () => { },
modUser: () => { }
}
const Context = React.createContext(defaultState)

const Test = () => {
const setUser = user => setState(prevState => ({ ...prevState, user }))
const modUser = () => setUser(state.user.toUpperCase()) // `state.user` never changes to updated value!
// user is 'Nick' at start...
const initState = {
user: 'Nick',
setUser,
modUser
}
// user changes to 'Bob' after 1 second...
useEffect(() => { setTimeout(() => setUser('Bob'), 1000) }, [])
const [state, setState] = useState(initState)
return <Context.Provider value={state}>
<div>Parent user is {state.user}</div>
<TestInner />
</Context.Provider>
}

const TestInner = () => {
const state = useContext(Context)
// user (should) change to uppercase 'BOB' after 2 seconds...
useEffect(() => { setTimeout(() => state.modUser(), 2000) }, [])
return <div>Child user is {state.user}</div>
}

export default Test

最佳答案

您可以将回调传递给状态 setter 。仔细查看您的代码,无需将 setUser 或 modUser 包装在 useCallback 中,因为在 const [state, setState] = useState(initState); 之后,您永远不会更改它们。以下可以工作并初始化状态一次,因此不需要在重新渲染测试时重新创建 mod 和 setUser(因为它们仅在第一次渲染时使用,然后被忽略。

const { useState, useContext, useEffect } = React;
const Context = React.createContext();

const Test = () => {
//use callback to set state with initial value, after
// first render the callback will not be called again
// until component is unmounted and re mounted
const [state, setState] = useState(() => ({
setUser: user =>
setState(prevState => ({ ...prevState, user })),
modUser: () =>
setState(state => ({
...state,
user: state.user.toUpperCase(),
})),
user: 'Nick',
}));
//get the setUser function to pass it to useEffect as a dependency
const { setUser } = state;
useEffect(() => {
setTimeout(() => setUser('Bob'), 1000);
}, [setUser]);
return (
<Context.Provider value={state}>
<div>Parent user is {state.user}</div>
<TestInner />
</Context.Provider>
);
};
const TestInner = () => {
const { modUser, user } = useContext(Context);
useEffect(() => {
setTimeout(() => modUser(), 2000);
}, [modUser]);
return <div>Child user is {user}</div>;
};

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

关于ReactJS 上下文 > 从状态函数引用最新状态值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59041701/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com