I have a feeling this has something to do with the react render cycle but I can't figure out what. Thanks a lot for taking the time to view my question.
Asked
Active
Viewed 180 times
-1
-
Have you tried this with componentDidMount, instead of componentWillMount? I believe componentWillMount is being deprecated. See https://stackoverflow.com/questions/46043832/why-componentwillmount-should-not-be-used – geochanto Dec 05 '18 at 19:53
-
its all because of when the render was called. just for testing. use a `setTimeout` and give a delay of 200-500ms and see what is the result – hannad rehman Dec 05 '18 at 19:54
-
Hi guys, thanks for checking my code I have tried your suggestions but not much has changed at all, any other suggestions?? – Ruairidh Grass Dec 06 '18 at 19:14
-
@hannadrehman you want me to put a setTimeout on the render() function?? – Ruairidh Grass Dec 06 '18 at 19:27
-
Please add code as text, not an image of code. Are `fetchAllArtists`/`fetchAllEvents` asynchronous? The console does not reflect the state of the time you were logging those things. Instead it is only evaluated when you expand it (see the blue icon). – str Dec 06 '18 at 19:36
-
Hey @str here's what the fetchAllArtists looks like on another function: `const fetchAllArtists = (array) => { firebaseArtists.once("value") .then((snapshot) => { const artists = firebaseLooper(snapshot); array.push(...artists); }) }` Sorry if it looks terrible, I'm not sure how to post code on here. As you can see the function takes in the array and populates it from the data in the firebase database. My problem is that the render function happens before the state is populated – Ruairidh Grass Dec 06 '18 at 20:18
-
Possible duplicate of [How do I return the response from an asynchronous call?](https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call) – str Dec 06 '18 at 20:29
-
for testing yes. you can put it in render. just see weather delayed call has the values – hannad rehman Dec 07 '18 at 06:57
1 Answers
0
Have you tried initializing your state in the class constructor
method? This way, the class's state will be initialized with the default values before the first attempt to render:
class Home extends Component {
constructor(props) {
super(props);
this.state = {
allEvents: [],
allArtists: []
};
}
...
...
}
Also, I agree with George Chanturidze's comment about using the componentDidMount
lifecycle method instead of componentWillMount
.
UPDATE: Added a snippet in an unsuccessful attempt to reproduce the issue
class App extends React.Component {
state = {
concatArray: [],
es6Array: [],
pushArray: []
};
componentWillMount = () => {
var concat = this.state.concatArray.concat({
name: "A_concat",
value: 1
}).concat({
name: "B_concat",
value: 2
});
this.state.pushArray.push({
name: "C_push",
value: 3
});
this.state.pushArray.push({
name: "D_push",
value: 4
});
this.setState({
concatArray: concat,
es6Array: { ...this.state.es6Array,
...[{
name: "E_es6",
value: 5
}, {
name: "F_es6",
value: 7
}]
}
});
};
render = () => {
console.clear();
console.log(this.state);
console.log(this.state.concatArray);
console.log(this.state.concatArray[0]);
console.log(this.state.pushArray);
console.log(this.state.pushArray[0]);
console.log(this.state.es6Array);
console.log(this.state.es6Array[0]);
return null;
};
}
const rootElement = document.getElementById("root");
ReactDOM.render( < App / > , rootElement);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>

Kevin M. Lapio
- 378
- 1
- 4
- 8
-
Hi guys, thanks for checking my code I have tried your suggestions but not much has changed at all, any other suggestions?? – Ruairidh Grass Dec 06 '18 at 19:01
-
Hi, @RuairidhGrass. I added a snippet to my answer in an effort to reproduce the "undefined" result when indexing for the fist array item with [0]. I tried to mirror the relevant pieces of your code, such as initializing state outside of using the class constructor and retaining componentWillMount. In my case, all three of my console.log statements appear to work as expected, including logging the state, logging the whole array, and logging the first array item. Are you able to provide a snippet that reproduces the issue or maybe include more of your code that might be applicable? – Kevin M. Lapio Dec 06 '18 at 19:34
-
Hi @Kevin I really appreciate your efforts! I think the problem may lie in my `fetchAllArtists(array)` method. It's a method that fetches data from a firebase database and then populates the array with that data. The function lives in a separate js file in an effort to keep my code dry. This is what said function looks like: `const fetchAllArtists = (array) => { firebaseArtists.once("value") .then((snapshot) => { const artists = firebaseLooper(snapshot); array.push(...artists); }) }` – Ruairidh Grass Dec 06 '18 at 20:28
-
@RuairidhGrass I am still failing to duplicate the "undefined" exactly, but I know that you should avoid mutating the array by way of using the Array.push() method and instead use this.setState to pass the new arrays to your respective state properties. This is better explained on some of the top answers here: https://stackoverflow.com/questions/37435334/correct-way-to-push-into-state-array. I updated my example to include how this would be handled for using the Array.concat() method as well as the ES6 syntax. I also included using Array.push() in a failed attempt to reproduce the issue. – Kevin M. Lapio Dec 06 '18 at 21:00
-
Hey @kevin I've posted an answer bellow with some images of it working. thanks – Ruairidh Grass Dec 07 '18 at 12:04