我可能会误解反应上下文通常如何工作,但我认为应该如何工作
我有一个主应用程序,具有如下的Context提供程序
export default function app(){
return <contextObj.Provider value={Complex Object with multiple properties...}>
<Main/>
</contextObj.Provider>
}
我的主要应用程序如下
export default function main(){
//Have imported the context class and am using it
let store = React.useContext(myContext)
return <React.Fragment>
<comp1 max={store.valueX} />
<comp2 />
</React.Fragment>
}
在comp2内部,修改上下文objext内部的valueX
export default function comp2(){
//Have imported the context class and am using it
let store = React.useContext(myContext)
return <buttonComp onClick={()=>store.valueX=3} />
}
所以从理论上说comp1应该接收更新后的值并重新渲染? 这就是我所坚持的,因为更改context属性不会导致comp1重新呈现。
任何帮助将不胜感激。
答案 0 :(得分:2)
就像正常的组件状态一样,您不能仅直接更改(分配)上下文的值。您需要将值包含在state中,并传递回调以更改该状态(或使用useDispatch
):
export default function App() {
const [value, setValue] = useState({
/* Complex Object with multiple properties */
});
const updateX = (newX) =>
setValue((prevValue) => {
return { ...prevValue, valueX: newX };
});
return (
<contextObj.Provider value={{ ...value, updateX }}>
<Main />
</contextObj.Provider>
);
}
export default function Comp2() {
//Have imported the context class and am using it
let store = React.useContext(myContext);
return (
<ButtonComp
onClick={() => {
store.updateX(3);
}}
/>
);
}
您可能需要将状态和回调移动到为此专门制作的组件中-例如MyContextProvider
仅包含状态并将其子级包装在MyContext.Provider
中。
export function MyContextProvider({ initialValue, children }) {
const [value, setValue] = useState(initialValue);
const updateX = (newX) =>
setValue((prevValue) => {
return { ...prevValue, valueX: newX };
});
return (
<MyContext.Provider value={{ ...value, updateX }}>
{children}
</MyContext.Provider>
);
}
export default function App() {
return (
<MyContextProvider
initialValue={/* Complex object with multiple properties */}
>
<Main />
</MyContextProvider>
);
}
但是,如果要在App
内派生具有多个属性的复杂对象,则像在我的第一个示例中那样直接使用Context.Provider
可能会更容易。
此外,请记住始终capitalize your components' names:
注意:始终以大写字母开头组件名称。
React将以小写字母开头的组件视为DOM标签。 例如,
<div />
代表HTML div标签,而<Welcome />
表示一个组件,并且要求Welcome
在范围内。要了解有关此约定背后原因的更多信息,请阅读 JSX In Depth。
答案 1 :(得分:1)
您不应直接在子级内部更改上下文。
相反,您应该调用一个函数/ reducer来改变上下文。
现在正在发生什么,您正在修改对象“存储”(该对象是您的上下文)中的一个值“ valueX”。为了做出反应,该对象仍然生活在相同的内存位置,因此未检测到更改。
cbr已经正确回答了您应该做什么。