Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React.js “Invariant Violation: findComponentRoot”

Tags:

reactjs

I know the mistake is from the nested stuff and nested _.map function but I can't figure out how to do this.

Below a part of the render function:

What I want to do is:

  1. Check is this.props.currencylist exists
  2. Then display a <select> dropdown
  3. with the <options> coming from the this.props.currencylist

{ 
  this.props.currencylist ?
  <select  id="fiatselector" onChange={this.onSelectCurrency} value {this.props.selectedcurrency}>
  { 
     _.map(this.props.currencylist, function(currency) { 
       return <option value={currency}> {currency} </option>  
     })
  }
  </select>
  : 
  ""
}    

thanks a lot!

Btw, at the first render it works perfectly, it bugs when the have to be updated, rerendering with a new currencylist trigger the error

like image 684
François Richard Avatar asked Jan 05 '15 09:01

François Richard


2 Answers

The actual problem here is the space around the value.

<option> {x} </option>

It should be:

<option>{x}</option>

The former ends up rendering:

<option><span> </span>{x}<span> </span></option>

The browser removes the span wrappers, but React still expects them to be there.

like image 126
Brigand Avatar answered Sep 17 '22 22:09

Brigand


I was able to reproduce your error. Apparently you need to add the key attribute to your option tags. I wish I could provide a better explanation, but I don't know quite enough about ReactJs to explain.

Here is the relevant change based on your snippet (only change here is adding the key attribute. I just used the currency as the key here):

_.map(this.props.currencylist, function(currency) {
     return <option key={currency} value={currency}> {currency} </option>
})

Here is a simple example I used for testing (Slightly modified rendering but same idea):

var CurrentSelector = React.createClass({
    render: function() {
        var options = this.props.currencylist.map(function(currency) {
            return <option key={currency} value={currency}> {currency} </option>
        });
        if (this.props.currencylist) {
            return <div><select id="fiatselector">{options}</select></div>
        } else {
            return <div></div>
        }
    }
});

var App = React.createClass({
    getInitialState: function() {
        return {
            currencylist: [1,2,3],
            selectedcurrency: 1,
        }
    },
    render: function() {
        return (
            <div>
                <CurrentSelector
                    currencylist={this.state.currencylist}
                    selectedcurrency={this.state.selectedcurrency} />
                <button onClick={this.handleClick}>test</button>
            </div>
        );
    },
    handleClick: function() {
        this.setState({
            currencylist: [2, 3, 4, 5],
            selectedcurrency: 2,
        })
    }
});
like image 26
Gohn67 Avatar answered Sep 17 '22 22:09

Gohn67