我有一个上下文应该在树中传递多个状态。 设置 Provider 值的正确方法是什么?
我应该如何传递上下文?
//Example:
interface Context {
state1: number,
state2: number,
}
const MyContext = React.createContext<Context|null>(null)
const MyFC: React.FC = (props)=>{
const [state1,setState1] = useState<number>(0) //To pass down
const [state2,setState2] = useState<number>(0) //To pass down
const [state3,setState3] = useState<number>(0) //Not to pass down
return(
<MyContext.Provider value={????}>
{/* components */}
<MyContext>
)
}
答案 0 :(得分:1)
您可以将键控数组传递给值:
value={{'state1':[state1,setstate1],'state2':[state2,setstate2]}}
然后你可以检索每个数据:
const context = React.useContext(MyContext);
const [state1,setstate1] = context['state1'];
const [state2,setstate2] = context['state2'];
或者直接:
const [state1,setstate1] = React.useContext(MyContext)['state1'];
const [state2,setstate2] = React.useContext(MyContext)['state2'];
您可以添加所需的州数。
答案 1 :(得分:1)
在上下文中传递复杂状态的选项有多种。
选项 1:拆分不会一起更改的上下文
如果组成上下文的元素不是紧密相关的,请考虑将上下文拆分为不同的上下文。这样你就可以传递单个状态,而不必处理“统一”状态的问题。
方案二:使用useReducer组合相关状态
<块引用>当使用 useState hook 时,建议为 每个元素,因为与类组件中的状态不同,更新 状态的单个元素可能会导致不必要的复杂性。
使用状态是功能组件中保存状态最常用的工具。
然而,当需要更复杂的状态(和状态管理)时,useReducer 可用于将状态包装在单个对象中。然后你可以将reducer的状态作为上下文的值传递
function reducer(state,action) {
switch(action.type){
//Cases:
//.... (works like redux reducer)
default:
return state
}
}
const MyContext = React.createContext<Context|null>(null)
const MyFC: React.FC = (props)=>{
const [compressedState,dispatch] = useReducer(reducer,{state1:0,state2:0})
const [state3,setState3] = useState<number>(0) //Not to pass down
return(
<MyContext.Provider value={compressedState}>
{/* components */}
<MyContext>
)
}
选项 3:useMemo
当前面的选项都不可行时, useMemo 是要走的路。 只需将需要传递的所有元素组合起来,即可创建一个值,该值仅在至少一个依赖项发生变化时更新。
const MyContext = React.createContext<Context|null>(null)
const MyFC: React.FC = (props)=>{
const [state1,setState1] = useState<number>(0) //To pass down
const [state2,setState2] = useState<number>(0) //To pass down
const [state3,setState3] = useState<number>(0) //Not to pass down
const contextValue= useMemo(()=>{
return{
state1: state1,
state2: state2
}
},[state1,state2]);
return(
<MyContext.Provider value={contextValue}>
{/* components */}
<MyContext>
)
}
关于 useMemo 的最后说明 当我们需要传递 useState(状态和设置状态)或 useReducer(状态和分派)这两个元素时,使用备忘录也变得有用。
在上下文中,我们应该始终避免在 value
prop 内放置一个内联对象。正如文章开头所说,这个对象在每次渲染时重新创建(新的内存地址),导致检查它的钩子重新渲染(因为观察到的内存值改变了)以及在小部件树中。< /p>
在这种情况下使用备忘录可能会变得很少,因为它可以避免传递内联对象:
//Example for useReducer. Works also with useState.
const contextValue = useMemo(() => {
return { state, dispatch };
}, [state, dispatch]);
来源: