Meteor React changing the state with a function passed to child


#1

Hi people!

I have a component that passes state down to one child to be shown on screen and passes down a function to another child so that child can make changes which will update the state of the parent and thus update the state that was passed down to the first child.

My issue is when the function is called from child 2 which is up on the parent I get the error:
Uncaught TypeError: Cannot set property ‘layer2’ of undefined

Parent:

constructor(){
         super();	
             this.state = {
               
                 layer1: <img id="layer1" className="img-responsive center-block" src="1.png" />,
                 layer2: <img id="layer2" className="img-responsive center-block"  src="2.png" />,
                 layer3:  <img id="layer3" className="img-responsive center-block" " src="3.png" />
               
         };
    }
    
      renderView(layer){
            if(layer === "layer2"){
                            this.state.layer2 = <img id="layer1" className="img-responsive center-block" src="4.png" />;  
            }
     }

I have done a console.log so I know this function is getting called.
This is how I pass it into the child component from the parent:

<ChildContainer  renderView={this.renderView}/>

Within the child when a button is clicked this happens:

this.props.renderView("layer2");

Thanks for the help I am very new to this!

UPDATE:

In the constructor of the parent I have done:
this.renderView = this.renderView.bind(this);

this now lets the renderView be called without error. The issue is it does nothing.
I have put a console.log before and after the this.state.eyesLayer part of the function and they both show.


#2

you should not put react-elements into state. It is meant for internal state (some key-value-pairs) of your component. In general, try to avoid state at all, unless you really need it.

The render-function of react-classes runs, whenever the state or its props have changed. Props change happen, when the parent component passes different props to this child-component. State, however, is updated with this.setState({key:value});

You must not change the state by updating its properties (like this.state.layer2 = ...) and as mentioned above, it makes no sense to me to put a react-element int the state.

What i would do is the following:

in the child-view, assign a clickhandler to the button, like:

(...)
<button onClick=(() => this.props.onButtonClicked(1)) >button 1</button>
<button onClick=(() => this.props.onButtonClicked(2)) >button 2</button>
(...)
```

and then in your parent, you pass onButtonClicked to the Childview, similar as you did with renderView::slight_smile: 

`<ChildContainer onButtonClicked={this.onButtonClicked} />`

with


```
onButtonClicked(layer) {
  this.setState({currentLayer: layer});
}
```
and in render:

```
render() {
 (..)
 <img 
   id={`layer${this.state.currentLayer}`} 
   className="img-responsive center-block"  
   src={`${this.state.currentLayer}.png`} />,
 (..)  
  
}
```