I'm having a hard time understanding why I can't do something like this.
loadPostsFromServer: function() {
$.ajax({
url: '/allPosts',
dataType: 'json',
success: function(data) {
console.log(data);
this.setState({posts:data, items:data});
//this.setState({items:data});
}.bind(this),
error: function(xhr, status, err) {
console.error(this.props.url,status, err.toString());
}.bind(this)
});
},
loadUserFromServer: function() {
$.ajax({
url: '/user',
dataType: 'json',
success: function(data) {
this.setState({user:data.local});
//console.log(this.state.user);
}.bind(this),
error: function(xhr, status, err) {
console.error(this.props.url,status, err.toString());
}.bind(this)
});
},
getInitialState: function() {
return {
posts: [],
items: [],
user: []
}
},
componentDidMount: function() {
this.loadPostsFromServer();
this.loadUserFromServer();
//this.setState({items: this.state.posts});
//setInterval(this.loadPostsFromServer, this.props.pollInterval);
},
render: function() {
<div className="Posts">
<List user={this.state.user} posts={this.state.items} />
</div>
}
Where List can be something like this and can't do the this.props.user print
var List = React.createClass({ //has to be called list
render: function() {
return (
<p>{this.props.user}</p>
<ul>
{
this.props.posts.map(post){
return (<p>{post.title}</p>)
})
}
</ul>
)
}
});
but can do this:
var List = React.createClass({
render: function() {
return (<p>{this.props.user}</p>)
}
});
Basically I'm passing two props in my real function, and the ajax call is delivering down a array user, with user info, and array post with post info. I can display the post info fine, and the user info is complete as well, however I cannot actually display the user info received from the ajax get call. I printed out the state of the array as well and it was complete and filled. However passed down it would return messages like cannot read {this.props.user.firstName} and such, however writing it the second way and not including posts, it works fine. How can I use both props in a map function?
Be careful, in render function, you always need a wrap tag to make React work. You should add <div> tag to the render of List component.
var List = React.createClass({ //has to be called list
render: function() {
return (
<div> <-- ALWAYS HAS A WRAP TAG
<p>{this.props.user}</p>
<ul>
{
this.props.posts.map(post){
return (<p>{post.title}</p>)
})
}
</ul>
</div>
)
}
});
This code below works because there is <p> to wrap contents.
var List = React.createClass({
render: function() {
return (<p> <-- WRAP TAG
{this.props.user}
</p>)
}
});
Related
UPD: How can I display elment of the array in my component (WeatherCityName - h2)? It can be seen that the array is loaded, but when I point out the property - an error occurs, it may be a problem in the syntax?
var WeatherBox = React.createClass({
handleWeatherSubmit: function(text) {
$.ajax({
url: this.props.url,
dataType: 'json',
type: 'POST',
data: 'cityName=' + text,
success: function(data) {
this.setState({data: data});
}.bind(this),
error: function(xhr, status, err) {
console.error(this.props.url, status, err.toString());
}.bind(this)
});
},
getInitialState: function() {
return {data: []};
},
render: function() {
return (
<div className="wetherBox">
<h1> Weather</h1>
<WeatherForm onWeatherSubmit={this.handleWeatherSubmit} />
<WeatherCityName data={this.state.data[0]} />
<WeatherList data={this.state.data} />
</div>
);
}
});
var WeatherCityName = React.createClass({
render: function(){
return(
<h2>{this.state.data[0].cityName}</h2>
);
}
});
Sure, just put <h2>{weatherItem.cityName}</h2> directly in the <div>.
var WeatherList = React.createClass({
render: function() {
var weatherNodes = this.props.data.map(function(weatherItem) {
return (
<div className="city-item-with-title">
<h2>{weatherItem.cityName}</h2>
<WeatherItem
cityid={weatherItem.cityid}
type={weatherItem.type}
src={weatherItem.src}
temp={weatherItem.temp}
tempFrom={weatherItem.tempFrom}
tempTo={weatherItem.tempTo}
key={weatherItem.id}
/>
</div>
);
});
return (
<div className="weatherList">
{weatherNodes}
</div>
);
}
});
Edit: I'm not sure which weather item you want to use as a title, perhaps this.props.data[0]?
Edit 2: Just assumed you want to use the first weather item.
Edit 3: One title for each weatherItem, grouped inside a div together with the corresponding weatherItem.
var Movie = React.createClass({
getInitialState: function() {
$.ajax({
url: "getjsonarray.php",
dataType: 'json',
method: "POST",
data: {
startpoint: 0,
perpage: 2
},
success: function(data) {
this.setState({
json: data
}, function() {
}.bind(this));
}.bind(this),
});
return null;
},
render: function() {
return (
<div>
{
this.state.json.map(function(object, i){
return (
<div key={i}>
<h1>Movie {i}</h1>
<h2>Genre {i}</h2>
</div>
);
})
}
</div>
);
}
});
ReactDOM.render(<Movie/>, document.getElementById('container'));
Here I'm trying to get json array from back end iterate through array via react js. But I only get this error,
TypeError: this.state is null
is there any way to return value with ajax responcejson array?
This is what I get from back end,
[{"id":"1","image":"http:\/\/images.prd.mris.com\/image\/V2\/1\/Yu59d899Ocpyr_RnF0-8qNJX1oYibjwp9TiLy-bZvU9vRJ2iC1zSQgFwW-fTCs6tVkKrj99s7FFm5Ygwl88xIA.jpg","price":"$1,975,000 ","address":"609 W Gravers Ln","area":"4,820 SqFt","beds":"5","baths":"5","desc":"Situated between fairmount park and the prestigious philadelphia cricket club, this beautiful 2+ acre property is truly","subdesc":"Courtesy of HS Fox & Roach-Chestnut Hill Evergreen"},{"id":"2","image":"http:\/\/images.prd.mris.com\/image\/V2\/1\/vGoNjc2jHGb87GlnnDQlf6LxeOUgIOn0bL6Wvn1nEnig2Ntq6W7xN5cOQBZZeNxl9O42DOkHUw0LNnj1ZB2KHA.jpg","price":"$1,500,000","address":"1220-32 N Howard St","area":"4,900 SqFt","beds":"1","baths":"1","desc":"A once in a lifetime opportunity to own a unique live \/ work space in one of philadelphia's most popular neighborhoods.","subdesc":"Courtesy of ll Banker Preferred-Philadelphia"}]
The problem here is that ajax is async so getInitialState goes first, then it goes straight to render, the api call is still in transit and you don't actually set state until the response is received. I would suggest setting initial state of json to an empty array and then add a componentDidMount function that does the ajax request and updates the state of json.
getInitialState: function() {
return {
json: []
}
},
componentDidMount: function() {
$.ajax({
url: "getjsonarray.php",
dataType: 'json',
method: "POST",
data : {startpoint: 0, perpage: 2},
success: function(data) {
this.setState({json: data}, function(){
}.bind(this));
}.bind(this),
});
},
In my own apps whenever i have a component that is dependent on a api call to get its data, I add a loading state to my component that comes in initially as true, and then while true I render something different or some sort of spinner. Then once the api call is finished it will set the loading state to false and update the data state.
Your problem is that your code breaks the life cycle of that component. You should
1. make the AJAX call and, once you have the value you need, then create the component.
2. create the component and then update it using the values from the AJAX response.
You should get server data/response in componentDidMount lifecycle method of your component. Your code can be like this
var Movie = React.createClass({
getInitialState: function () {
this.state = { json: [] };
},
componentDidMount: function () {
var self = this;
$.ajax({
url: "getjsonarray.php",
dataType: 'json',
method: "POST",
data: {
startpoint: 0,
perpage: 2
},
success: function (response) {
/* okay, now re-render component with received response */
self.setState({
json: response
});
}
});
},
render: function () {
/* in initial render json array is empty */
var json = this.state.json;
return (
<div>
{
json.map(function (object, i) {
return (
<div key={i}>
<h1>Movie {i}</h1>
<h2>Genre {i}</h2>
</div>
);
})
}
</div>
);
}
});
ReactDOM.render(<Movie/>, document.getElementById('container'));
I have the following ReactJS code:
var CommentList = React.createClass({
render: function(){
var commentNodes = this.props.data.map(function(comment){
return (
<Comment author={comment.author} key={comment.id}>
{comment.text}
</Comment>
);
});
return (
<div className="commentList">
{commentNodes}
</div>
);
}
});
And in CommentBox....
var CommentBox = React.createClass({
loadCommentFromServer: function() {
$.ajax({
url: this.props.url,
dataType: 'json',
cache: false,
success: function(data) {
this.setState({
data: data
});
}.bind(this),
error: function(xhr, status, err) {
console.error(this.props.url, status, err.toString());
}.bind(this)
});
},
},
getInitialState: function() {
return {
data: []
};
},
componentDidMount: function() {
this.loadCommentFromServer();
setInterval(this.loadCommentFromServer, this.props.pollInterval);
},
render: function() {
return (
<div className = "commentBox" >
<h1> Comments </h1>
<CommentList data ={ this.state.data } />
<CommentForm />
</div>
);
}
});
In getInitialState(), I already assign value for data and in CommentList also add property data which get value from state.
When I try to run, I got this error:
Cannot read property 'map' of undefined in CommentList.
It looks like you simply aren't getting the data you want back from the jQuery.ajax.
success: function(data) {
// before setting state, log here and find out what data is
// it could need to be turned into JSON? data = data.toJSON();
// or simply this to be safe
data = data || [];
this.setState({
data: data
});
}
i have an app which loads data from mongodb to list component like this
React.render(<ProductsList url="http://localhost:3000/data"/>, document.getElementById('products'));
and then i try make a http get call to ge the data like this
var ProductsList = React.createClass({
loadData: function() {
$.ajax({
url: this.props.url,
dataType: 'json',
success: function(data) {
<ProductsList url={data}/>
},
error: function(xhr, status, err) {
console.error(this.props.url, status, err.toString());
}
});
},
render: function() {
this.loadData();
var products = this.props.url.map(function(product) {
return (
<li key={product._id}>
<Product data={product} />
</li>
)
});
return (
<ul className="clearfix">
{products}
</ul>
);
}
});
but when i load the app i get this error Uncaught TypeError: this.props.url.map is not a function what could the problem be ?
map is not a function for strings, check the documentation for array map: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map
Furthermore, not related to your error, but your function loadData returns undefined, because you are just making the ajax call. In order to make this work, you need to use the state object of the react component call this.setState() in your success/error hooks.
it's seems like you are not clear about the props and state of React you have to follow in below mentioned way
var ProductsList =React.createClass({
getInitialState:function()
{
return{
url:[]
}
},
componentDidMount:function()
{
var that=this;
$.ajax({
url: 'https://api.github.com/users/mralexgray/repos',
dataType: 'json',
success: function(data) {
that.setState({url:data});
},
error: function(xhr, status, err) {
console.error(this.props.url, status, err.toString());
}
});
},
ChangeContent:function()
{
this.setState({content:"change Content"});
},
render:function()
{
var Products = this.state.url.map(function(product) {
return (
<li key={product._id}>
{product.full_name}
</li>
)
});
return(
<div>
{Products}
</div>
)
}
});
React.render(
<ProductsList />,
document.getElementById('example')
);
Demo
I have the following component that is a lot like the React.js main tutorial. Basically, I have an api that I'm pulling from and trying to load the data:
var Box = React.createClass({
getInitialState: function () {
return {
data: {
items: []
}
};
},
loadStuffFromServer: function() {
$.ajax({
url: this.props.url,
dataType: 'json',
cache: false,
success: function(data) {
this.setState({data: data});
}.bind(this),
error: function(xhr, status, err) {
console.error(this.props.url, status, err.toString());
}.bind(this)
});
},
componentDidMount: function() {
this.loadStuffFromServer();
},
render: function() {
var blah = this.state.data;
return (
<div>
{ blah }
</div>
);
}
});
However when I put blah there, I get the error: Uncaught Error: Invariant Violation: Objects are not valid as a React child (found: object with keys {items}). If you meant to render a collection of children, use an array instead or wrap the object using createFragment(object) from the React add-ons. Check the render method ofBox.
I call my component with react rails and <%= react_component('Box',url: "URLHERE", pollInterval: 1000) %>
Use Array (data.items) instead of Object
var blah = this.state.data.items;
__________________________^^^^^^___
render: function () {
var blah = this.state.data.items.map(function (item) {
return <p>
{ item.content }
</p>;
});
return <div>
{ blah }
</div>;
}
Adding to what Alexander said, you don't have to assign state's value to a variable. You can directly do- inside the div tag
<div> { this.state.data.items } <div>
And Use a .map to get the values.
{this.state.data.items.map(objval =>
<div>
{objval.name}
</div>
)}
Hope it helps :)