简体   繁体   中英

React Context Component Rendering

I am having issues with rendering components using context. The AppProvider class has a function called add which changes the state. I am passing the add function and the state to components using context. Whenever an Onclick event occurs on the component the add method sets a new state.

So my question is when onclick occurs on either of the components the state changes. So why isn't the change reflected on both components?

When I console.log(this.state) within the add function. The components have been initialized with same state value but both components maintain their own instances of state.

It seems like the AppProvider is passing a new instance each time its called. Is it supposed to behave in this way? how could I share the same instance different components using context.

import React from "react";           
import ReactDOM from "react-dom";

var Mycontext=React.createContext();

class AppProvider extends React.Component {
  constructor(props) {
   super(props)
   this.state=({ total:12323 }) 
  } 

  add(){
   var x=this.state.total
   x++;
   this.setState({total:x})
  } 

  render() {
   return (
    <div>
     <Mycontext.Provider 
      value = {{add:this.add.bind(this),state:this.state.total}}>
      {this.props.children}
     </Mycontext.Provider>
    </div>
   )
  }      
}

var ContextConsumer = Mycontext.Consumer;

var Para2=(props) => {
 console.log(props)
 return (<p onClick={()=>props.add()}>{props.data}</p>)
}

var Para1=(props) => {
 return (<p onClick={()=>props.add()}>{props.data}</p>)
}

var App=(props) => {
 return (
  <div>
   <AppProvider>
    <ContextConsumer>
     {({state,add}) => <Para1 data={state} add={add}/>}
    </ContextConsumer>
   </AppProvider>
   <AppProvider>
    <ContextConsumer>
     {({state,add}) => <Para1 data={state} add={add} />
    </ContextConsumer>
   </AppProvider>
  </div>
  )
 }

 ReactDOM.render(<App/>,document.getElementById("index"));

@CameronDowner Suppose the components are nested inside divs and are not direct siblings using AppProvider just once doesnt work in this case wouldnt work.

How do I pass a single instance of AppProvider when the components are not direct sibling.Is that possible??

 <div class="container"> <div class="row"> <AppProvider> <div class="col m6 s6 l6"> <ContextConsumer> {({ state, add }) => <Para1 data={state} add={add}/>} </ContextConsumer> </div> <div class="col m6 s6 l6"> <ContextConsumer> {({ state, add }) => <Para2 data={state} add={add} /> } </ContextConsumer> </div> </AppProvider> </div> </div> 

As mentioned in the comments by @Dave Newton your code is very difficult to understand and actually contains some syntax errors. It's always easier to help when the question has clean code.

I have managed to spot the issue though. It is being caused by the fact you have two <AppProvider /> components.

  <AppProvider>
    <ContextConsumer>
      {({ state, add }) => <Para1 data={state} add={add} />}
    </ContextConsumer>
  </AppProvider>
  <AppProvider>
    <ContextConsumer>
      {({ state, add }) => <Para2 data={state} add={add} /> }
    </ContextConsumer>
  </AppProvider>

This means there are two states and they are passed individually to each component.

If you replaced this with one, like so, you're components will share one state and therefore both update.

  <AppProvider>
    <ContextConsumer>
      {({ state, add }) => <Para1 data={state} add={add} />}
    </ContextConsumer>
    <MyContext.Consumer>
      {({ state, add }) => <Para2 data={state} add={add} /> }
    </ContextConsumer>
  </AppProvider>

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