0

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

1
  • 4
    Unrelated, but I can't read that code at all. Please consider using consistent, rational indentation. No clue what's doing what. Commented Aug 31, 2018 at 14:39

1 Answer 1

1

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>
Sign up to request clarification or add additional context in comments.

5 Comments

Good eye--I couldn't see anything up in there.
I apologize for the bad identation and I tried to use online code beautifiers but they only made the problem worse
@xxxgrime If you're interested, I can add to the bottom of my answer how I refactored your code to spot the mistake.
I extended my question just a little bit could you check it out
The answer is the same. Consumers do not need to be direct children but just existing somewhere inside the context provider. The code you have posted works. See: codesandbox.io/s/kooy58315o

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.