反应上下文;子组件不重新渲染
React context; child component not rerendering
我可能误解了 React 上下文的一般工作方式,但我认为它应该如何工作:
我有一个主应用程序,其中包含如下上下文提供程序
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内部,修改context 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 应该接收更新后的值并重新渲染?
这就是我卡住的地方,因为改变上下文 属性 不会导致我的 comp1 重新渲染。
就像正常的组件状态一样,您不能直接改变(分配给)上下文的值。您需要在状态中包含该值并向下传递回调以更改该状态(或使用 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:
Note: Always start component names with a capital letter.
React treats components starting with lowercase letters as DOM tags.
For example, <div />
represents an HTML div tag, but <Welcome />
represents a component and requires Welcome
to be in scope.
To learn more about the reasoning behind this convention, please read
JSX In Depth.
你不应该直接改变 children 中的上下文。
相反,您应该调用一个会改变上下文的函数/reducer。
现在发生了什么,您正在修改一个值,object“存储”中的“valueX”(object 是您的上下文)。对于 React,object 仍然存在于相同的内存位置,因此未检测到任何变化。
cbr 已经正确回答了你应该做什么。
我可能误解了 React 上下文的一般工作方式,但我认为它应该如何工作:
我有一个主应用程序,其中包含如下上下文提供程序
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内部,修改context 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 应该接收更新后的值并重新渲染? 这就是我卡住的地方,因为改变上下文 属性 不会导致我的 comp1 重新渲染。
就像正常的组件状态一样,您不能直接改变(分配给)上下文的值。您需要在状态中包含该值并向下传递回调以更改该状态(或使用 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:
Note: Always start component names with a capital letter.
React treats components starting with lowercase letters as DOM tags. For example,
<div />
represents an HTML div tag, but<Welcome />
represents a component and requiresWelcome
to be in scope.To learn more about the reasoning behind this convention, please read JSX In Depth.
你不应该直接改变 children 中的上下文。
相反,您应该调用一个会改变上下文的函数/reducer。
现在发生了什么,您正在修改一个值,object“存储”中的“valueX”(object 是您的上下文)。对于 React,object 仍然存在于相同的内存位置,因此未检测到任何变化。
cbr 已经正确回答了你应该做什么。