简体   繁体   中英

Why can't update a value in a child component (with react context) when a provider component parent state change?

I am trying to use React Context in my project. I implemented a provider component and I am consuming the data in two child components. But when I update the state of the Provider component from one of the children, the other child is not re-rendered with the data from the provider component.

I am using these characteristics of React Context to avoid passing the props from component to component. As I have implemented it in the past

Codesandbox Example

// Parent Provider

const {Provider, Consumer} = React.createContext()

class ShoppingCartProvider extends React.Component{
 constructor(props){
            super(props)
            this.state = {
                  order: {},
                  Total: 0,

            }
      }

      addOrder = (key) => {
            const order = this.state.order
            let totalOrder = this.state.Total
            order[key] = order[key] + 1 || 1
            this.setState({order})
            totalOrder = totalOrder + 1
            this.setState({Total: totalOrder})

      }
      render(){
            return(
                  <Provider value={{
                        order: this.state.order,
                        addOrder: this.addOrder,
                        totalOrder: this.state.Total
                  }}>
                  <div>{this.props.children}</div>
                  </Provider>     
            )
      }
}

export {ShoppingCartProvider, Consumer as ShoppingCartConsumer}

// child that changes the parent state

import React, {useContext } from 'react';

const ItemProducto = props =>{
      const {product} = props

      const {addOrder} = useContext(ShoppingCartConsumer)

      return <Grid item>
                 <div css={botonAdd}
                   onClick={()=>{
                        addOrder(product._id)
                  }}>Add</div>
             </Grid>

}



export default ItemProducto

//This is not re-rendered when the state in parent component changes



import React, {useContext, useEffect, useState} from 'react';

const Header = props =>{      

      const {totalOrder} = useContext(ShoppingCartConsumer)
      const [count, setcount] = useState(totalOrder)

      useEffect(()=>{
            setcount(totalOrder)
      })
      return (
           <div>                                                                
              <Grid item  css={numeroDinero}>{count}</Grid>                                                              
           </div> 

      )
}


export default Header

I expect a re-render in Header child when ItemProducto child change a Total state property.

Everything in your code checks out except one. The useContext() expects the actual context as an argument not the consumer. In your case you passed in the consumer by doing this: export {..., Consumer as ShoppingCartConsumer } .

All you need to do to fix the issue is this: In ShoppingCartContext change:

const { Provider, Consumer } = React.createContext() to

const ShoppingCartContext = React.createContext(); .

And in your render :

render() {
    return (
      <ShoppingCartContext.Provider
        value={{
          order: this.state.order,
          addOrder: this.addOrder,
          totalOrder: this.state.Total
        }}
      >
        <div>{this.props.children}</div>
      </ShoppingCartContext.Provider>
    );
  }

Then change your export to: export { ShoppingCartProvider, ShoppingCartContext };

Modify the imports in the Header and ItemProducto accordingly, and do not forget to pass ShoppingCartContext to their respective useContext() s.

For more info on useContext see here

编辑上下文和钩子

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