简体   繁体   中英

What is the reason behind react component showing the changes of state inside them?

When we have many components in react project and sometimes we use multiple pre-made components for making a page. While using onChange inside a component and showing the result of the state , in this case, what functionality of components allows the value render of state and how it works when we have multiple components inside other components. Here is an Ex...

 function Component() {
  const [value, setValue] = React.useState()
  const handleChange = val => {
    setValue(val)
  }
 return (
    <React.Fragment>
      <Compo1  //perform adding +1 
        onChange={handleChange}
      />
      Value: {value} // 1
     {console.log("value", value)} // showing right value
      <Compo2>
        <Compo3>
          <Compo1  //perform adding +1
            onChange={handleChange}
          />
          Value:{value} // undefined
          {console.log("value", value)} // showing right value
        </Compo3>
        {console.log("value", value)} // showing right value
      </Compo2>
    </React.Fragment>
  )
}
render(<Component />)

In this case why console is showing the right value but the state variable value is showing undefined.

The only way I can get that code to do what you say it does is when you incorrectly use React.memo on Compo3:

 const Compo1 = ({ onChange }) => ( <button onClick={() => onChange(Date.now())}>+</button> ); const Compo2 = ({ children }) => <div>{children}</div>; const Compo3 = React.memo( function Compo3({ children }) { return <div>{children}</div>; }, () => true//never re render unless you re mount ); function Component() { const [value, setValue] = React.useState(88); const handleChange = React.useCallback(() => { setValue((val) => val + 1); }, []); return ( <React.Fragment> <Compo1 //perform adding +1 onChange={handleChange} /> works: {value}----- <Compo2> <Compo3> <Compo1 //perform adding +1 onChange={handleChange} /> broken:{value}----- </Compo3> </Compo2> </React.Fragment> ); } ReactDOM.render( <Component />, document.getElementById('root') );
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script> <div id="root"></div>

Maybe you can do the same if you do some wacky stuff with shouldComponentUpdate

A component will render when:

  1. When the parent renders the child and the child is a functional component (not wrapped in React.memo)
  2. When the parent renders the child with different prop values than the previous render.
  3. When value in [value,setValue]=useState() or when this.state changes (when state changes).
  4. When someContext in value = useContext(someContext) changes (even if value doesn't change).
  5. In most cases when value in value = useCustomHoom() changes but this is not guaranteed for every hook.
  6. When Parent renders and passes a different key prop to Child than the previous render (see 2). This causes the Child to unmount and re mount as well.

In the example the Compo3 wants to re render because Parent is re rendered due to a state change and passes different props (props.children).

Compo3 is not a functional component because it's wrapped in React.memo. This means that Compo3 will only re render if props changed (pure component).

The function passed as the second argument to React.memo can be used to custom compare previous props to current props, if that function returns true then that tells React the props changed and if it returns false then that tells React the props didn't change.

The function always returns true so React is never told that the props changed.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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