React Cannot read property '__reactInternalInstance$2f71vks24hx' of null [duplicate] - reactjs

Here is the problematic component in question.
const UserList = React.createClass({
render: function(){
let theList;
if(this.props.data){
theList=this.props.data.map(function(user, pos){
return (
<div className="row user">
<div className="col-xs-1">{pos}</div>
<div className="col-xs-5">{user.username}</div>
<div className="col-xs-3">{user.recent}</div>
<div className="col-xs-3">{user.alltime}</div>
</div>
);
}, this);
} else {
theList = <div>I don't know anymore</div>;
}
console.log(theList);
return (
theList
);
}
});
Whenever I attempt to return {theList}, I receive a Cannot read property '__reactInternalInstance$mincana79xce0t6kk1s5g66r' of null error. However, if I replace {theList} with static html, console.log prints out the correct array of objects that i want. As per the answers, I have tried to return both {theList} and theList but that didn't help.
In both cases, console.log first prints out [] which I assume is because componentDidMount contains my ajax call to get json from the server and has not fired yet before the first render(). I have tried to check against
this.props.data being null but it does not help.
Here is the parent component if it helps:
const Leaderboard = React.createClass({
getInitialState: function(){
return ({data: [], mode: 0});
},
componentDidMount: function(){
$.ajax({
url: 'https://someurlthatreturnsjson',
dataType: 'json',
cache: false,
success: function(data) {
this.setState({data: data});
}.bind(this),
error: function(xhr, status, err) {
console.error('https://someurlthatreturnsjson', status, err.toString());
}.bind(this)
});
},
render: function(){
return (
<div className="leaderboard">
<div className="row titleBar">
<img src="http://someimage.jpg"></img>Leaderboard
</div>
<HeaderBar />
<UserList data={this.state.data}/>
</div>
);
}
});

Ah OK, there were some interesting problems in here, but you were so close. The big one, with react you must always return a single top-level element (e.g. a div). So, your variable theList was actually an array of divs. You can't return that directly. But you can return it if it's wrapped in a single parent div.
const mockData = [
{
username: 'bob',
recent: 'seven',
alltime: 123,
},
{
username: 'sally mae',
recent: 'seven',
alltime: 133999,
},
];
var $ = {
ajax(opt) {
setTimeout(() => {
opt.success(mockData);
}, 200);
}
}
const UserList = React.createClass({
render: function(){
let theList;
if (this.props.data && this.props.data.length) {
theList = this.props.data.map(function(user, pos){
return (
<div key={user.username} className="row user">
<div className="col">{pos}</div>
<div className="col">{user.username}</div>
<div className="col">{user.recent}</div>
<div className="col">{user.alltime}</div>
</div>
);
});
} else {
theList = <div>There is NO data</div>;
}
return <div>{theList}</div>;
}
});
const Leaderboard = React.createClass({
getInitialState: function(){
return ({data: [], mode: 0});
},
componentDidMount: function(){
$.ajax({
url: 'https://someurlthatreturnsjson',
dataType: 'json',
cache: false,
success: function(data) {
this.setState({data: data});
}.bind(this),
error: function(xhr, status, err) {
console.error('https://someurlthatreturnsjson', status, err.toString());
}.bind(this)
});
},
render: function(){
return (
<div className="leaderboard">
<UserList data={this.state.data}/>
</div>
);
}
});
ReactDOM.render(
<Leaderboard/>,
document.getElementById('container')
);
.col {
width: 200px;
float: left;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<script src="https://facebook.github.io/react/js/jsfiddle-integration-babel.js"></script>
<div id="container">
<!-- This element's contents will be replaced with your component. -->
</div>
To explain the fiddle a little bit. Don't worry about the weird looking var $ stuff, I'm just stubbing out jQuery's ajax method so I can return some fake data after 200ms.
Also, for me jsfiddle gives me a 'bad config' message when I run it, but I close the message and the result is there. Don't know what that's about.

return (
{theList}
)
should just be
return theList
because you are not inside JSX at that point. What you're doing there will be interpreted as
return {
theList: theList
}
That's ES6 shorthand properties syntax.

Error can also arise from accessing nested state that doesn't exist:
I lack the reputation to comment, so adding an answer for future assistance -- I ran into this same issue for a different reason. Apparently, the error is triggered from an earlier error throwing off react's internal state, but the error is getting caught somehow. github issue #8091
In my case, I was trying access a property of state that didn't exist after moving the property to redux store:
// original state
state: {
files: [],
user: {},
}
// ... within render function:
<h1> Welcome {this.state.user.username} </h1>
I subsequently moved user to redux store and deleted line from state
// modified state
state: {
files: [],
}
// ... within render function (forgot to modify):
<h1> Welcome {this.state.user.username} </h1>
And this threw the cryptic error. Everything was cleared up by modifying render to call on this.props.user.username.

There is a small problem with the if statement:
if(this.props.data !== []){
should be:
if(this.props.data){
this.props.data is null, if the ajax call returns null. alternatively the code could be more elaborate.
const data = this.props.data;
if(data && data.constructor === Array && data.length > 0) {

Not sure if this is how you want to do it, but it works for me.
edit:
const UserList = React.createClass({
render: function() {
if(this.props.data){
return this.props.data.map(function(user, pos){
return (
<li> className="row user">
<span>{pos}</span>
<span>{user.username}</span>
<span>{user.recent}</span>
<span>{user.alltime}</span>
</li>
);
});
} else {
return <li>I don't know anymore</li>;
}
}
});

I encountered this error when I rendered a stateless component and decided to remove the react-root-element (wrapping div) after rendering it with basic dom manipulation.
Conclusion: be aware of this, better don't do it.

Related

react components not talking to each other

I've built a basic restuarant recommendation app that filters by location using the YELP api. The api was responding to my requests with the response object and everything was appending to my divs perfectly, but I realized that for my project, I needed to make a new layer for the data listing. Here are the relevant portions of my two components as they are now:
display-recs:
var DisplayRecs = React.createClass({
render: function() {
var recsLoop = [];
if (this.props.recommendations) {
for (var i=0; i < this.props.recommendations.length; i++) {
recsLoop.push(<Recommendations item={this.props.recommendations[i]} />)
}
}
console.log(this.props.recommendations);
return (
<div className="DisplayRecs">
{recsLoop}
</div>
);
}
});
var mapStateToProps = function(state, props) {
return {
recommendations: state.recommendations
};
};
recommendations:
var Recommendations = React.createClass({
render: function() {
<div id="bizData">
<div id='nameList'>{this.props.item.name}</div>
<div id='phoneList'>{this.props.item.phone}</div>
<div id='ratingList'>{this.props.item.rating}</div>
</div>
}
});
var mapStateToProps = function(state, props) {
return {
recommendations: state.recommendations
};
};
I cannot figure out why the nameList, phoneList, and ratingList will not print onto the dom. When I view the elements tab in my devtools, all i see is an empty displayrecs div. I've tried to just change things by guessing, but it's not been fruitful. Can any of you see an obvious problem with the current code?
Thanks
Your Recommendations react component's render function doesn't have any return statement. Try doing this:
var Recommendations = React.createClass({
render: function() {
return ( <div id="bizData">
<div id='nameList'>{this.props.item.name}</div>
<div id='phoneList'>{this.props.item.phone}</div>
<div id='ratingList'>{this.props.item.rating}</div>
</div>);
}
});
Also add a key to the Recommendations components as #Vikramaditya recommends:
recsLoop.push(<Recommendations key={i} item={this.props.recommendations[i]} />)

Coordinating props of encapsulated components when rendering data in reactjs

I am building a recipe box in reactJS. My objective is hide ingredients within the button, listing the recipe title. Thus when a person clicks on a button titled "cheesecake" they will see its respective ingredients. The booleans in communicating when and when not to do this makes sense as it relates to "Onclick". However, I'm unsure of how to coordinate this action when fetching data given that my ingredients data (this.props.ingredients) is implicated within recipetitlebutton component. I tried re-initializing the ingredients component within the title button thinking that I can just define it within the recipeTitleButton when I mapped over the data. However, this didn't work and it didn't feel clean. Anyway, I hope this makes sense. Any help is greatly appreciated.
Thanks
var recipes = [{
recipe_title: "Cheesecake",
ingredients: "cream cheese, graham crackers, butter, eggs"
}, {
recipe_title: "Lasagna",
ingredients: " ricotta cheese, ground beef, pasta shells, parsely"
}, {
recipe_title: "Spaghetti",
ingredients: "noodles, pasta sauce, ground beef"
}]
var RecipeTitleButton = React.createClass({
getInitialState: function() {
return {
showIngredients: false
}
},
onClick: function() {
this.setState({
showIngredients: true
})
},
render: function() {
<Ingredients ingredients={this.props.ingredients}/>
return (
<div>
<button type="button" className="recipe_title_button" class="btn btn=primary btn-lg">{this.props.recipe_title}</button>
{this.state.showIngredients ? <Ingredients/>: null}
</div>
)
}
})
var Ingredients = React.createClass({
render: function() {
return (
<div id="ingredients" className="recipe_title_ingredients">
{this.props.ingredients}
</div>
)
}
})
var MainRecipeDisplay = React.createClass({
getInitialState: function() {
return {
recipeDataObject: recipes
}
},
render: function() {
var Pages = this.state.recipeDataObject.map(function(recipeContents) {
<RecipeTitleButton recipe_title={recipeContents.recipe_title} ingredients={recipeContents.ingredients}/>
})
return (
<div>
{Pages}
</div>
)
}
})
ReactDOM.render(<MainRecipeDisplay/>, document.getElementById('content'))
It appears that you're not actually passing the click handler to any of the elements. So you've defined the onClick method in RecipeTitleButton, but you're not passing this to anything. The solution is probably as simple as passing the <button> element a property onClick={/* The function that you want to fire on click */}.
First of all, change the name of the click handler to something like onClickHandler, for sanity. Click handlers are called with an event argument, which you probably don't need for your purposes but is important to know about (for example, if you need to prevent event propagation or have the click handler figure out which button was clicked).
Then the render function for RecipeTitleButton should look like:
render: function() {
<Ingredients ingredients={this.props.ingredients}/>
return (
<div>
<button type="button" className="recipe_title_button" onClick={this.onClickHandler.bind(this)} class="btn btn=primary btn-lg">{this.props.recipe_title}</button>
{this.state.showIngredients ? <Ingredients/>: null}
</div>
)
}
In case you're wondering, we bind the function to this so that the context remains the RecipeTitleButton component, instead of the window.
Oh, as an aside, it'd be easier to test this if you put it in a JSFiddle
Actually I figured it out. Was very simple. First, React doesn't recognize changing the setState value with a mere {setState({showingredients: true}). I had to use a function to make this explicit {setState(function(){return showIngredients:true)}. Second,in order to render the ingredients component within in my recipeTitle component, I only had to indicate props within {this.showIngredients ? :"null"/>. This way, I was allowed to define the ingredients prop within my recipeTitleButton. Code is Below:
var recipes = [{
title: "Cheesecake",
ingredients: "cream cheese, graham crackers, butter, eggs"
}, {
title: "Lasagna",
ingredients: " ricotta cheese, ground beef, pasta shells, parsely"
}, {
title: "Spaghetti",
ingredients: "noodles, pasta sauce, ground beef"
}]
var Layout = React.createClass({
getInitialState: function() {
return {
recipeDataObject: recipes,
showIngredients: false
}
},
render: function() {
var recipeContents = this.state.recipeDataObject.map(function(currentRecipe) {
return (
<RecipeTitleButton title={currentRecipe.title} ingredients={currentRecipe.ingredients}/>
)
})
return (
<div>
{recipeContents}
</div>
)
}
})
var RecipeTitleButton = React.createClass({
getInitialState: function() {
return {
showIngredients: false
}
},
handleRecipeButtonClick: function() {
**this.setState(function() {
return {
showIngredients: true
}**
});
},
render: function() {
return (
<div>
<button type="button" onClick={this.handleRecipeButtonClick.bind(this)} className="recipe_button">{this.props.title}</button>
**{this.state.showIngredients && <Ingredients ingredients={this.props.ingredients}/>}**
</div>
)
}
})
var Ingredients = React.createClass({
render: function(){
return(
<div className= "ingredients_list">
{this.props.ingredients}
</div>
)
}
})

react js displaying ajax data on function call by passing parameter

I am currently trying to learn react by building a simple app that works with a JSON array by calling a certain API. I would then like to show the results of the array in a list item and when click one of the list-item and then it returns a parameter and call an api and display data in other part of the page.
I have successfully called the API and am showing the correct data in the list-item but I am struggling to figure out how to show the data after the click in another part of the page.
So I currently have this in my page:
<div class="col-lg-3 col-md-3">
<div class="block-job-list" id="JobCardBlock"></div>
</div>
<div class="col-lg-9 col-md-9">
<div class="block-job-list" id="JobDetailBlock"></div>
</div>
<script type="text/jsx">
var JobCard = React.createClass({
// get game info
loadGameData: function() {
document.getElementById("overlay").style.display = "block";
var a_token = window.localStorage.getItem('access_token');
$.ajax({
type: 'GET',
url: this.props.source,
data: {
page: 1,
},
dataType: "json",
beforeSend: function(xhr) {
xhr.setRequestHeader("Authorization", "Bearer " + a_token);
},
success: function(data) {
$('#overlay').hide();
this.setState({
data: data.order_list.data
});
}.bind(this),
error: function(xhr, status, err) {
$('#overlay').hide();
console.error('#GET Error', status, err.toString());
}.bind(this)
});
},
getInitialState: function() {
return {
data: []
}
},
componentDidMount: function() {
this.loadGameData();
},
render: function() {
return ( < div className = "CurrentGame" >
< JobList data = {
this.state.data
}
/> < /div>
);
}
});
var JobList = React.createClass({
displayData: function(e) {
var a_token = window.localStorage.getItem('access_token');
$.ajax({
type: 'POST',
url: 'http://zipship-beta.herokuapp.com/job_detail',
data: {
order_id: e,
},
dataType: "json",
beforeSend: function(xhr) {
xhr.setRequestHeader("Authorization", "Bearer " + a_token);
},
success: function(data) {
$('#overlay').hide();
this.setState({
data: data.order_list
});
console.log(this.state.data);
}.bind(this),
error: function(xhr, status, err) {
$('#overlay').hide();
console.error('#GET Error', status, err.toString());
}.bind(this)
});
},
render: function() {
if (!this.props.data) {
return null;
}
return (
<ul className="list-group">
{
this.props.data.map(function(jobDetail, i) {
return <li className="list-group-item" key=jobDetail.id} onClick={()=>{this.displayData(jobDetail.id)}}>
</div>
</li>
},this)
}
</ul>
);
}
});
</script>
If you are looking to make actions of job list change the state of job card here are two options you might consider.
The easiest of which is to create a parent react class such as JobInfo which simply acts as a container for both these elements.
render: function() {
<div>
<JobCard/>
<JobList/>
</div>
}
Then JobInfo would maintain state for both of these two objects. In React when you find ways to reduce state its always a good sign. Then the JobInfo object would have some function such as onListItemClick or updateJobCard. Since you are using your ajax request to update the state, it would be move up to this parent class since the state lives here. Then you simply pass this function down (as a prop) to the JobList object and use this for your onClick event on your list items. Now since the state of the parent is changed from the onClick event the state change will propagate down to both the JobList and JobCard info.
The other option you can look into is having an external event handler. These kind of methods are what you find in Flux structures. The idea use you JQuery or some event library to have your JobList object Trigger an event globally, and have your JobCard object subscribed to this event.
The second option I would recommend against. For most simple cases its completely unnecessary and to implement this type of system.
TLDR; Centralize your state and pass state altering functions as props.

How to render array passed to sub element in React JS?

I have simple example with JSON that has array in it.
It is loaded with ajax:
{somekey: "value1", somekey2: "value2", belongsto: ["me","you"]}
I can render it by for example:
<div>
belongsto: {this.state.data.belongsto}
</div>
But I would love to render it as list in subcomponent, so I am trying:
<Uli data={this.state.data.belongsto}/>
as:
var Uli = React.createClass({
render: function() {
return (
<ul className="Uli">
{
this.props.data.map(function(value) {
return <li key={value}>{value}</li>
})
}
</ul>
)
}
});
And that gives me:
Uncaught TypeError: Cannot read property 'map' of undefined
How this should be achieved?
You are loading your json data through AJAX asynchronously, and hence belongsto is undefined until you'll got the response from the server.
There are several solutions to solve this:
Add getDefaultProps method to your ULi component.
var Uli = React.createClass({
getDefaultProps() {
return {
data: []
}
},
render: function() {
return (
<ul className="Uli">
{this.props.data.map(function(value) {
return <li key={value}>{value}</li>
})}
</ul>
)
}
});
Use || operator:
<ul className="Uli">
{(this.props.data || []).map(function(value) {
return <li key={value}>{value}</li>
})}
</ul>
Prevent ULi rendering, if does not belongsto is undefined:
{this.state.data.belongsto && <Uli data={this.state.data.belongsto}/>}

Pass data from one component to another component without parent child relation

Here are my two components.
Component 1:
var Main = React.createClass({
getInitialState: function(){
return{
data: [],
values:[],
childRecord:[]
};
},
componentDidMount: function(){
$.ajax({
url: "data.json",
dataType: 'json',
success: function(data) {
this.setState({data: data});
}.bind(this),
error: function(xhr, status, err) {
console.error(this.props.url, status, err.toString());
}.bind(this)
});
render: function() {
var that = this,
data = this.state.data;
if(this.state.data.length > 0) {
data = this.state.data[0].values;
data = this.state.data[0].values[0].children;
}
var data = this.state.data;
if(this.state.data.length > 0) {
data = this.state.data[0].values;
}
var nestedData = data.map(function(Record, id) {
return(
<Tile key={id} data={Record} child={data}/>
);
});
return (
<div className="row main-container">
{nestedData}
</div>
);
}
});
*Component 2:*
var Tile=React.createClass({
render:function(){
return(
<div className="row">
<div className="tileForm">
<h3>{this.props.data}</h3>
</div>
</div>
);
}
});
I want to render some part of json in Tile Component. The other components have parent child relation so I can render the data easily, but I dont know how to render the data in Tile component since there is no relation b/w Tile Component and other components. I am using routing to call Tile component and rendering Main component by using DefaultHandler, this is not the complete code.
Any kind of help will be appreciated.
Thanks
Fhm
You want to use the Flux (or something similar) pattern for this use case: https://github.com/facebook/flux - it was designed to solve this exact problem.
You would encapsulate your data (the JSON payload) in a shared Store. Both your components could then read from this store independent of how they are related to each other.
If the data needs to change you would pair this store with an action creator that your components could call to trigger data refresh/mutate, etc.
This also is helpful for when you have a deep nesting of components because you can avoid having to deeply bubble down your data.

Resources