简体   繁体   English

反应上下文; 子组件不重新渲染

[英]React context; child component not rerendering

I may be misunderstanding how react context work in general, but how I think it should work goes like this:我可能误解了 React 上下文一般是如何工作的,但我认为它应该如何工作是这样的:

I have a main app that has the Context provider as following我有一个主应用程序,其上下文提供程序如下

export default function app(){
   return <contextObj.Provider value={Complex Object with multiple properties...}>
     <Main/>
   </contextObj.Provider>
}

My main app is as follows我的主要应用程序如下

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

Inside of comp2, modify valueX inside of the context objext在 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} />
}

So in theory comp1 should receive the updated value and re-render?那么理论上 comp1 应该接收更新的值并重新渲染? This is where I'm stuck, as altering the context property isn't causing my comp1 to re-render.这就是我卡住的地方,因为更改上下文属性不会导致我的 comp1 重新渲染。

Just like normal component state, you can't just directly mutate (assign to) the value of the context.就像正常的组件状态一样,您不能直接改变(分配给)上下文的值。 You'll need to contain the value in state and pass down a callback to change that state (or use useDispatch for example):您需要包含 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);
      }}
    />
  );
}

You'll probably want to move the state and the callbacks into a component specifically made for this - eg MyContextProvider which just contains the state and wraps its children in MyContext.Provider .您可能希望将状态和回调移动到专门为此创建的组件中 - 例如MyContextProviderMyContextProvider包含状态并将其子项包装在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>
  );
}

However, if you're deriving your complex object with multiple properties inside App , it may be easier to just use the Context.Provider directly like in my first example.但是,如果您在App派生具有多个属性的复杂对象,则直接使用Context.Provider可能会更容易,就像在我的第一个示例中一样。

Also, remember to always capitalize your components' names :另外,请记住始终将组件名称大写

Note: Always start component names with a capital letter .注意:组件名称始终以大写字母 开头

React treats components starting with lowercase letters as DOM tags. React 将以小写字母开头的组件视为 DOM 标签。 For example, <div /> represents an HTML div tag, but <Welcome /> represents a component and requires Welcome to be in scope.例如, <div />代表一个 HTML div 标签,但<Welcome />代表一个组件并且要求Welcome在范围内。

To learn more about the reasoning behind this convention, please read JSX In Depth .要了解有关此约定背后的推理的更多信息,请阅读JSX In Depth

you should not mutate directly the context inside the children.你不应该直接改变孩子内部的上下文。

rather you should call a function/ reducer which will mutate the context.相反,您应该调用一个函数/reducer 来改变上下文。

what is happening right now, you are modifying one value, "valueX" inside an object "store" (the object is your context).现在正在发生的事情,您正在修改一个值,“valueX”在对象“存储”中(该对象是您的上下文)。 For react the object still lives on the same memory location, so no change is detected.对于反应,对象仍然存在于相同的内存位置,因此没有检测到任何变化。

cbr already answered correctly what you should rather do. cbr 已经正确回答了您应该做的事情。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM