unable to set state from fetch function in React Component

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP



unable to set state from fetch function in React Component



I'm trying to set a state from a fetch function and the api seems to return the json correctly. But the state never seems to be populated with the data from the api. Does anyone see the problem? The code seems to run fine and doesn't display any errors so I'm not sure what the problem is. Here is code:




var count = 0;
const ActivityRow = props => (
<tr>
<td>props.activity.Date.toString()</td>
<td>props.activity.ActivityType</td>
<td>props.activity.Value</td>
</tr>
);

function ActivityTable(props)
const ActivityRows = props.activities.map(activity => (
<ActivityRow key=activity.id activity=activity />
));
return (
<table className="bordered-table">
<thead>
<tr>
<th>Date</th>
<th>Activity Type</th>
<th>Value</th>
</tr>
</thead>
<tbody>ActivityRows</tbody>
</table>
);


function formatDate(date)
var hours = date.getHours();
var minutes = date.getMinutes();
var ampm = hours >= 12 ? "pm" : "am";
hours = hours % 12;
hours = hours ? hours : 12;
minutes = minutes < 10 ? "0" + minutes : minutes;
var strTime = hours + ":" + minutes + " " + ampm;
return (
date.getMonth() +
1 +
"/" +
date.getDate() +
"/" +
date.getFullYear() +
" " +
strTime
);


class ActivityAdd extends React.Component
constructor()
super();
this.handleSubmit = this.handleSubmit.bind(this);

handleSubmit(e)
e.preventDefault();
var form = document.forms.ActivityAdd;
this.props.createActivity(
id: count++,
Date: formatDate(new Date()),
ActivityType: form.Activity.value,
Value: form.Value.value
);
// clear the form for the next input
form.Activity.value = "";
form.Value.value = "";

render()
return (
<div>
<form name="ActivityAdd" onSubmit=this.handleSubmit>
<input type="text" name="Activity" placeholder="Activity" />
<input type="text" name="Value" placeholder="Value" />
<button>Add</button>
</form>
</div>
);


class App extends React.Component
constructor()
super();
this.state = activities: ;
this.createActivity = this.createActivity.bind(this);


loadData()
fetch("/api/activities")
.then(response => response.json())
.then(data =>
console.log("Total count of records:", data._metadata.total_count);
);
this.setState( activities: data.records );

createActivity(newActivity)
fetch("/api/activities",
method: "POST",
headers: "Content-Type": "application/json" ,
body: JSON.stringify(newActivity)
)
.then(response => response.json())
.then(updatedActivity =>
const newActivities = this.state.activities.concat(newActivity);
this.setState( activities: newActivities );
);

render()
return (
<div>
<h1>Diabetes Self Management App</h1>
<hr />
<ActivityTable activities=this.state.activities />
<hr />
<ActivityAdd createActivity=this.createActivity />
</div>
);


ReactDOM.render(<App />, document.getElementById("contents"));



Any suggestions will be appreciated.





Where are you calling the loadData method?
– skylerfenn
Aug 13 at 2:50


loadData





this.setState( activities: data.records ); move this line to then, although if u move it there, you should put this in another object before entering then function.
– jsDevia
Aug 13 at 3:22




1 Answer
1



The setState is outside the scope of data, so data is undefined, which lead to the failure of setting state.


setState


data


data




loadData()
fetch('/api/activities').then(response =>
response.json()
).then(data =>
console.log("Total count of records:", data._metadata.total_count);
);
// undefined here as data is not existed
this.setState( activities: data.records );



The solution is to move setState inside the promise return.


setState


var count = 0;
const ActivityRow = props => (
<tr>
<td>props.activity.Date.toString()</td>
<td>props.activity.ActivityType</td>
<td>props.activity.Value</td>
</tr>
);

function ActivityTable(props)
const ActivityRows = props.activities.map(activity => (
<ActivityRow key=activity.id activity=activity />
));
return (
<table className="bordered-table">
<thead>
<tr>
<th>Date</th>
<th>Activity Type</th>
<th>Value</th>
</tr>
</thead>
<tbody>ActivityRows</tbody>
</table>
);

function formatDate(date)
var hours = date.getHours();
var minutes = date.getMinutes();
var ampm = hours >= 12 ? "pm" : "am";
hours = hours % 12;
hours = hours ? hours : 12;
minutes = minutes < 10 ? "0" + minutes : minutes;
var strTime = hours + ":" + minutes + " " + ampm;
return (
date.getMonth() +
1 +
"/" +
date.getDate() +
"/" +
date.getFullYear() +
" " +
strTime
);


class ActivityAdd extends React.Component
constructor()
super();
this.handleSubmit = this.handleSubmit.bind(this);

handleSubmit(e)
e.preventDefault();
var form = document.forms.ActivityAdd;
this.props.createActivity(
id: count++,
Date: formatDate(new Date()),
ActivityType: form.Activity.value,
Value: form.Value.value
);
// clear the form for the next input
form.Activity.value = "";
form.Value.value = "";

render()
return (
<div>
<form name="ActivityAdd" onSubmit=this.handleSubmit>
<input type="text" name="Activity" placeholder="Activity" />
<input type="text" name="Value" placeholder="Value" />
<button>Add</button>
</form>
</div>
);


class App extends React.Component
constructor()
super();
this.state = activities: ;
this.createActivity = this.createActivity.bind(this);


loadData()
fetch("/api/activities")
.then(response => response.json())
.then(data =>
console.log("Total count of records:", data._metadata.total_count);
// must be in this then scope
this.setState( activities: data.records );
);


createActivity(newActivity)
fetch("/api/activities",
method: "POST",
headers: "Content-Type": "application/json" ,
body: JSON.stringify(newActivity)
)
.then(response => response.json())
.then(updatedActivity =>
const newActivities = this.state.activities.concat(newActivity);
this.setState( activities: newActivities );
);

render()
return (
<div>
<h1>Diabetes Self Management App</h1>
<hr />
<ActivityTable activities=this.state.activities />
<hr />
<ActivityAdd createActivity=this.createActivity />
</div>
);


ReactDOM.render(<App />, document.getElementById("contents"));





I tried this and it still didn't work. Do you have any other suggestions?
– 15kitscs
Aug 14 at 3:11





Have you tried console.log(data.records) inside the then scope to see what is being printed out?
– Anh Pham
Aug 14 at 3:16


console.log(data.records)


then






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

Firebase Auth - with Email and Password - Check user already registered

Dynamically update html content plain JS

How to determine optimal route across keyboard