Reputation: 1378
I'm having trouble accessing data inside my state which I fetch from my database, this is my state:
state = {
inputDataArr: [],
inputDataArrTest: [
{
formID: 'test',
inputArr: [1, 2, 3],
labelArr: [4, 5, 6]
}
]
};
this is the collection I'm importing from the database:
{
"_id": {
"$oid": "5ba96b8ebffd923734090df4"
},
"inputArr": [
"value1",
"value2",
"value3"
],
"labelArr": [
"label1",
"label2",
"label3"
],
"formID": "5ba96b83bffd923734090df0",
"__v": 0
}
which is an object with 2 arrays in it, this is how I fetch it :
componentWillMount() {
fetch('/api/datas')
.then(data => data.json())
.then(datas => {
const filterdDatas = datas.filter(
data => data.formID == this.props.match.params.id
);
this.setState(currentState => ({
inputDataArr: [...currentState.inputDataArr, ...filterdDatas]
}));
});
}
now when I console log inputDataArr and inputDataArrTest I get an array with an object inside, exactly the same, but when I console log InputDataArrTest[0] which is what you can see in my state I can see the arrays and the formID, but when I console log inputDataArr[0] I get undefined, really frustrating, anybody knows why?
Upvotes: 0
Views: 126
Reputation: 1634
Mapping and doing data manipulation inside the render is never a good idea and isn't easy to debug.
My suggestion is to initialize the state to an empty array, and call a method to return the mapped data.
constructor(props) {
super(props);
this.state = {
inputDataArr: []
};
}
render() {
const data = this.state.inputDataArr.map(...)
return <div>{data}</div>
}
This way state is initiated before first render and data
will return an empty array.
After componentDidMount
the state will update and will re-render with the new data.
As a side note, i would do the mapping in a third then
and set the state to the result itself.
Happy Coding.
Upvotes: 1
Reputation: 1378
renderLabels() {
const { inputDataArr } = this.state;
return (
!!inputDataArr.length &&
inputDataArr[0].labelArr.map((label, index) => (
<th key={index}>{label}</th>
))
);
}
conditional rendering solved my problem
Upvotes: 0
Reputation: 31024
I'm not sure where are you running the console.log
but setState
has a callback method that you can run after the actual data has been updated:
this.setState(currentState => ({
inputDataArr: [...currentState.inputDataArr, ...filterdDatas]
}), () => {
// this is the callback for setState, you can access the updated data
console.log(inputDataArr);
});
Note If you run the console.log
in render
keep in mind that the first render
call will always run before the async data has been fetched.
Note #2 Do not use componentWillMount
at all and especially not for fetching data.
Use componentDidMount
instead.
Upvotes: 1
Reputation: 944
filteredDatas
before using ...filteredDatas
? Maybe it is not an Array and result to other thing or an empty Array.this.props.match.params.id
is defined and equal to the formID
property?If it exists only one object with unique formID
why don’t you use Array#find
instead of Array.filter
and then update your state with
this.setState(prevState => ({ dataArr: filteredDatas ? prevState.dataArr.concat([filteredDatas]) : prevState.dataArr // Here with Array#find, filteredDatas is null or a object not an Array });
Upvotes: 0