在反应上下文中传递多个状态

Passing multiple states in react context

我有一个上下文应该在树的多个状态中传递。 设置 Provider 值的正确方法是什么?

  1. 在适当的位置创建 object 不起作用,因为它在每个 re-render 处都是 re-built,导致 child 也变为 re-render如果上下文的实际内容没有改变(因为创建了一个新的 object,具有不同的内存地址,导致 child 认为 object 已更改)。

我应该如何传递上下文?

//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>
 )
}

您可以将键控数组传递给值:

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:拆分不一起更改的上下文

如果构成上下文的元素不是紧密相关,请考虑将上下文拆分为不同的上下文。这样你就可以通过单个状态而不必处理“统一”状态的问题。

方案二:使用useReducer合并相关状态

When using useState hook is advised to create a separate state for each element since, unlike the state in class components, updating single elements of a state can lead to unnecessary complexity.

使用状态是功能组件中最常用的保存状态的工具。

然而,当需要更复杂的状态(和状态管理)时,useReducer 可用于将状态包装在单个对象中。然后你可以将 reducer 的状态作为 context

的值传递
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 是可行的方法。 简单地组合所有需要传递的元素来创建一个值,该值仅在至少一个依赖项发生变化时更新。

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(state 和 set state)或 useReducer(state 和 dispatch)的两个元素时,使用备忘录也变得有用。

在上下文中,我们应该始终避免将内联对象放入value prop 中。正如 post 开头所说,这个对象在每次渲染(新内存地址)时都会重新创建,导致检查它的钩子重新渲染(因为观察到的内存值发生变化)以及向下小部件树。

在这种情况下,使用备忘录会变得很方便,因为它可以避免传递内联对象:

//Example for useReducer. Works also with useState.

const contextValue = useMemo(() => {
  return { state, dispatch };
}, [state, dispatch]);

来源: