React not loading data for Ajax call - javascript

I have built a React component and I want to put data in it when the component loads but I constantly get the Array as empty. To my understanding if I have to put data in a component I should do so in ComponentDidMount method.
Below is my code.
var Home = React.createClass({
componentDidMount(){
console.log('component mount');
var self = this;
var str = "junk string";
$.ajax({
url: "http://localhost:9000/checkoutcart/data/",
type : "get",
data : {
ajaxid: 4,
UserID: str
},
}).then(function (data) {
self.setState({movieItem: data});
});
},
getInitialState: function() {
console.log('getInitialState component mount');
return {movieItem:[]};
},
render: function() {
return (
<div>
<div>
<div>
<ol>
{this.state.movieItem.map(stuff => (
<li><h4>{stuff.title}</h4></li>
))}
</ol>
</div>
</div>
</div>
);
}
});

Related

ReactJS - moving list items between components

I am trying to create two components, one that holds the results of an API call from iTunes. I want to be able to click on any one of the items and move it to the empty component, moveResults, and then move it back to searchResults if it is clicked again. From other exercises, I feel like I am close, however I keep getting an error about the this.handleEvent = this.handleEvent.bind(this). Any ideas as to where I might have gone wrong and some possible solutions?
var App = React.createClass({
getInitialState: function() {
return {
searchResults: [],
moveResults: []
}
},
this.handleEvent = this.handleEvent.bind(this);
showResults: function(response) {
this.setState({
searchResults: response.results,
moveResults: []
})
},
search: function(URL) {
$.ajax({
type: 'GET',
dataType: 'json',
url: URL,
success: function(response) {
this.showResults(response);
}.bind(this)
});
},
handleEvent(trackId) {
const isInSearchResults = this.state.searchResults.includes(trackId);
this.setState({
searchResults: isInSearchResults ? this.state.searchResults.filter(i => i !== trackId) : [...this.state.searchResults, trackId],
moveResults: isInSearchResults ? [...this.state.moveResults, trackId] : this.state.moveResults.filter(i => i !== trackId)
});
},
componentDidMount() {
this.search('https://itunes.apple.com/search?term=broods')
},
render: function(){
return (
<div>
<Results searchResults={this.state.searchResults} handleEvent={this.handleEvent}/>
<Results searchResults={this.state.moveResults} handleEvent={this.handleEvent} />
</div>
);
}
});
var Results = React.createClass({
render: function(){
let handleEvent = this.props.handleEvent;
var resultItems = this.props.searchResults.map(function(result) {
return <ResultItem key={result.trackId} trackName={result.trackName} onClick={() => handleEvent(resultItems.id)} />
});
return(
<ul>
{resultItems}
</ul>
);
}
});
var ResultItem = React.createClass({
render: function(){
return <li> {this.props.trackName} </li>;
}
});
ReactDOM.render(
<App />, document.getElementById('root')
);

ReactJs - getInitialState not working

I'm playing with ReactJs, and i have this simple code
var User = React.createClass({
render: function () {
return(
<li>
{this.props.email}
</li>
);
}
});
var UserList = React.createClass({
reload: function () {
var xhr = new XMLHttpRequest();
xhr.open('get', "http://localhost:64501/Home/GetUsers", true);
xhr.onload = function () {
var result = JSON.parse(xhr.responseText);
this.setState({ data: result });
console.log(JSON.stringify(result));
}.bind(this);
xhr.send();
},
getInitialState: function () {
return {
data: [
{ email: "bob#gmail.com", id: "1" },
{ email: "boby#gmail.com", id: "2" }
]
};
},
componentDidMount: function () {
window.setInterval(this.reload, 3000);
},
render: function () {
if (this.props.data != null) {
var userNodes = this.props.data.map(function (user) {
return (
<User email={user.email} key={user.id } ></User>
);
});
return (
<div>
<ul>{userNodes}</ul>
</div>
);
}
else {
console.log("this.props.data is null");
return null;
}
}
});
ReactDOM.render(<UserList />, document.getElementById('root'));
I got 2 issues :
1 - the datas returned by getInitialState function are not rendered by the component.
2 - setState does not refresh the component in the reload function.
You are reading this.props.data and you should be reading this.state.data.
Note the difference between component properties, which come externally, and component internal state.
Just replace all this.props.data with this.state.data and your code should work.

Passing Ajax/service data between components in React.js

I am trying to pass data received in one component of a React application. On success I am taking the received data and setting the state and then trying to pass that data as a property of the next component. Once inside the second component I need to access the passed data via this.state so I can change the state in that component later. I seem to be encountering an issue with the DOM rendering before the data is received from the service. I have tried passing an already loaded array of values in place of this.state.data in <List data={this.state.data}/> and it seems to execute fine. How can assure that I have received the data from the service before rendering the DOM so that the data is passed all the way down to each component.
EDIT: added full implementation of the List element so explain the use of this.state
This is basically what I am trying to do:
var Box = React.createClass({
getInitialState: function() {
return {data: []};
},
loadTodosFromServer: function() {
$.ajax({
url: this.props.url,
dataType: 'json',
type: 'GET',
cache: false,
success: function(dataResponse) {
this.setState({data: dataResponse});
}.bind(this),
error: function(xhr, status, err) {
console.error(this.props.url, status, err.toString());
}.bind(this)
});
},
componentDidMount: function() {
this.loadFromServer();
},
render: function() {
return (<List data={this.state.data}/>);
}
});
var List = React.createClass({
getInitialState: function() {
return {data: this.props.data};
},
dragStart: function(e) {
this.dragged = e.currentTarget;
e.dataTransfer.effectAllowed = 'move';
// Firefox requires dataTransfer data to be set
e.dataTransfer.setData("text/html", e.currentTarget);
},
dragEnd: function(e) {
this.dragged.style.display = "block";
this.dragged.parentNode.removeChild(placeholder);
// Update data
var data = this.state.data;
var from = Number(this.dragged.dataset.id);
var to = Number(this.over.dataset.id);
if(from < to) to--;
if(this.nodePlacement == "after") to++;
data.splice(to, 0, data.splice(from, 1)[0]);
this.setState({data: data});
},
dragOver: function(e) {
e.preventDefault();
this.dragged.style.display = "none";
if(e.target.className == "placeholder") return;
this.over = e.target;
// Inside the dragOver method
var relY = e.clientY - this.over.offsetTop;
var height = this.over.offsetHeight / 2;
var parent = e.target.parentNode;
if(relY > height) {
this.nodePlacement = "after";
parent.insertBefore(placeholder, e.target.nextElementSibling);
}
else if(relY < height) {
this.nodePlacement = "before"
parent.insertBefore(placeholder, e.target);
}
},
render: function() {
var results = this.state.data;
return (
<ul>
{
results.map(function(result, i) {
return (
<li key={i}>{result}</li>
)
})
}
</ul>
);
}
});
ReactDOM.render(
<Box url="/api/comments"/>, document.getElementById('content')
);
The reason why your data load subsequent to component load is not rendering the data is because of this line in your List.render function:
var results = this.state.data;
Essentially, you have made a copy of your original props and assigned them to the state in the List component using the getInitialState method. And after that your state and props are delinked. Which means that if the props.data changes on the List component, the state doesn't know about it, so therefore nothing gets re-rendered.
So, instead of using state to initialize the results variable, use props.
var results = this.props.data
Here's how it would look like:
var List = React.createClass({
render: function() {
var results = this.props.data;
return (
<ul>
{
results.map(function(result, i) {
return (
<li key={i}>{result}</li>
)
})
}
</ul>
);
}
});
Now anytime the data changes, props get updated and eventually the results get re-rendered.
Updated to address the comments from the OP:
If you want to update the state of the list but want to be notified every time the props at the parent change, then you want to use the method componentWillReceiveProps so that when the data is obtained the child List is notified. And in this method you can set the new state:
componentWillReceiveProps: function(newProps) {
this.setState({data: this.props.data});
}
Once you do this, react will re-render the list for you.
Another update: To illustrate how this works I have put together an example here.
And here's the JS code for this:
let todos = ["Run","Swim","Skate"];
class MyList extends React.Component{
componentWillMount() {
console.log("Props are: ", this.props);
this.setState({list: this.props.items});
}
componentWillReceiveProps(newProps) {
console.log("Received Props are: ", newProps);
this.setState({list: newProps.items});
}
render() {
return (<ul>
{this.state.list.map((todo) => <li>{todo}</li>)}
</ul>);
}
}
class App extends React.Component{
constructor() {
super();
console.log("State is: ", this.state);
}
componentWillMount() {
this.setState({items: ["Fly"]});
}
componentDidMount() {
setTimeout(function(){
console.log("After 2 secs");
this.setState({items: todos});
}.bind(this), 2000);
}
render() {
return (<MyList items={this.state.items}/>);
}
}
ReactDOM.render(<App/>, document.getElementById("app"));

Unable to render json data in ReactJS components

I am trying to show data from package.json in my ReactJS components. I have seen many answers on SO and tried to implement it. It is neither showing any data nor an error.
This is package.json:
{
"name":"Clark Kent",
"job":"Superman"
}
This is my jsx:
var App = React.createClass({
getInitialState: function(){
return { myData: [] };
},
showResults: function(response){
this.setState({
myData: response
});
},
loadData: function(URL) {
var that = this;
$.ajax({
type: 'GET',
dataType: 'jsonp',
url: URL,
success: function(response){
that.showResults(response);
}
})
},
componentDidMount: function() {
this.loadData("package.json");
},
render: function(){
return(
<div>
<Component1 data={this.state.myData} />
<Component2 data={this.state.myData}/>
</div>
)
}
});
var Component1 = React.createClass({
render: function () {
return(
<div>Name: {this.props.data.name}</div>
)
}
});
var Component2 = React.createClass({
render: function () {
return(
<div>Job: {this.props.data.job}</div>
)
}
});
ReactDOM.render(<App/>, document.getElementById('container'));

load json with reactjs

I'll be very grateful who can help me with this line
I've this:
var Country = React.createClass({
render:function(){
return(
<nav>
<h2>list of country:</h2>
{ this.props.country}
</nav>
)
}
})
var Jugador =React.createClass({
componentWillMount: function(){
var pais;
var self = this;
$.getJSON("https://restcountries.eu/rest/v1/all", function(data){
for(pais in data)
{
console.log(pais, data[pais].name);
return(
<Country key={i} country={self.render(data[pais].name)}> </Country>
)
}
})
},
})
and it does not work, and appear this error
Uncaught Invariant Violation: createClass(...): Class specification must implement a render method.
Your Jugador component needs to implement a render method.
In React each component must have render method, you should implement it. I've refactored your code and now it look like this
var Country = React.createClass({
render: function() {
return <div>
{ this.props.country }
</div>
}
})
var Countries = React.createClass({
getInitialState: function () {
return { countries: [] };
},
componentWillMount: function(){
$.getJSON("https://restcountries.eu/rest/v1/all", function (data) {
this.setState({ countries: data })
}.bind(this))
},
render: function () {
var countries = this.state.countries.map(function (el, i) {
return <Country key={i} country={ el.name } />
}, this);
return <nav>
<h2>list of country:</h2>
<div>{ countries }</div>
</nav>;
}
})
Example

Categories