something about this.setState in class components is confusing me. in react docs, i read that this.setState may be asynchronous in react docs. im okay with this and i tested it with logging the updated value after this.setState. but it is really confusing me: when we call this.setState, react calls render method of the class to re-render the ui. but this.setState is asynchronous and it means that first render method will be called and ui will be re-rendered by react, then the value in the state will be changed! so how does component show us the updated value? i dont... am i thinking right?
thanks for helping.
this.setState is asynchronous and it means that first render method will be called and ui will be re-rendered by react, then the value in the state will be changed! so how does component show us the updated value? i dont... am i thinking right?
I think you missed something.setState is asynchronous which means that the actions are batched together for performance gains . But why ? since it's not a a WebAPI or server call?
This is because setState alters the state and causes rerendering. This can be an expensive operation and making it synchronous might leave the browser to behave unexpectedly.
Related
In react, we commonly use the useState hook to store data. We don't update the state directly, because the component doesn't re-render in this way. Now my question is, How did setState trigger the rendering under the hood?
A common concept can be setState call the rendering. But I think maybe there is something else. (something global object or state obj manipulation, something like this).
I don't understand how to setState trigger rendering under the hood. If anyone can explain it, it will be very helpful for me including others.
I am interested in understanding why setting a components state (setState()) is slow to update i.e. I may read an old value after the fact that I called setState(). Additionally i am interested in knowing if reading the component state also incurs a penalty to know if I should minimize the number of reads/writes to component state. I tried looking for the documentation at the react website but no dice. Thanks
React batch multiple setState() calls into a single update for performance.
Because this.props and this.state may be updated asynchronously, you should not rely on their values for calculating the next state.
https://reactjs.org/docs/state-and-lifecycle.html#state-updates-may-be-asynchronous
setState() is asynchronous, so you won't get the new value in the same function where you update it
Exactly when should we check if a component mounted or not ???
I have a lot of setState call and I encounter some time with the warning I wrote in the title.
Now I can avoid this by declaring a variable and initializing to true in componentDidMount and re asigning to false on componentWillUnmount, and then check when setState gets call.
But My Exact question is, Is it necessary to check every time setState calls, or this warning happens in specific cicumstances ? and I should check the variable on that time ?
Also will affect this warning on performance?
It can happen when you call setState asynchronously, e.g. window.fetch().then(...setState...) or await or inside a callback.
You could use this.isMounted() instead of your custom variable, but see also https://reactjs.org/blog/2015/12/16/ismounted-antipattern.html for better solutions.
I recently read through a large portion of the React and ReactDOM codebase in order to get an understanding of what happens when a call to setState occurs. At this point, I would say that I understand the sequence of events at a high level. A call to setState results in a message being added to a queue of updates that need to be processed. The updates are processed and changes to the DOM are only made if necessary.
Here's where I am lost. There are hundreds of blog posts discussing the asynchronous behavior of setState. While I don't doubt that setState is asynchronous, I cannot find a line of code in the ReactDOM codebase that would introduce asynchronous behavior. Does anyone know exactly where this happens?
First of all setState may be execute in async way, but it is not allwys executed as such. Ben Nadel list some of his findings in setState() State Mutation Operation May Be Synchronous In ReactJS
To summarize setStates seems to gets batched in situations where react can intercept originating event, like onClick handlers. Since react creates actual DOM from virtual react DOM (and since it is aware of semantics of attributes) it can wrap any of onClick handlers that you provide into something like this
wrappedHandler = () => {
turnBatchingOn()
originalHanlder()
executeBatched()
}
In this case you get async behavior, all setState calls get enqueued, and they get executed only after your original onClick handler has finished executing.
Note this is not actual react code it is just my speculation how it is async effect achieved. I understand it is not actual line of code that does it, but I think it could help you find it.
Best article explaining setState implementation that I found is on React Kung Fu
i think setState isn't async, but there is an optimization of multiple setState calls and in some cases sync canot be guaranteed.
Here's my problem:
I'm new at reactjs and I'm trying to make this app using SWAPI (swapi.co). For now I need to list characters and some info about them. The problem is I have this component called SelectedCharacter that returns some info about a character that was selected in a div.
The moment a character is passed through props to this component, I get a response via xmlhttp and the info is displayed. The thing is that I want to put a "Loading..." message while the data is fetched. This is how I was trying to figure it out:
I set up the componentWillReceiveProps function, where I test if I'll need to load stuff and the componentDidUpdate, where I fetch the data from this api and update the status.
I know, from react life cycle, that a render is called between componentWillReceiveProps and componentDidUpdate, and it indeed is.
I expected, then, that if I did this:
render() {
if (criteria) {
return <div>Loading...</div>
}
}
The thing is: even if this criteria is true (I tested it using console.log()), the message doesn't show until the next re-render. Am I doing anything too wrong here? If it helps, my code is at github.com/piubellofelipe/StarWars, the problem is at the selected_characters.js, in the src paste.
Thanks
I've been looking at your code, trying to work this out for you and I don't have any concrete answers for you, but I've noticed a few things that may be making things a bit unpredictable.
1. Calling forceUpdate
componentWillReceiveProps(){
this.setState({loading:true})
this.forceUpdate();
}
Calling setState will trigger a render, so the call the forceUpdate is not required here. This means there are more renders occurring than you might expect.
I believe this may be the cause of your issue for a pretty complicated reason. From the setState docs
... setState() is also asynchronous, and multiple calls during the same cycle may be batched together.
And from the forceUpdate docs
Calling forceUpdate() will cause render() to be called on the component...
My theory is that the call render triggered by setState, asynchronously setting loading to true, is being delayed and the one from forceUpdate is sneaking in first, while loading is still false.
2. Updating props
this.props.selected.moviesList = moviesListNames;
Components should never, ever, update their own props. Usually, this would be stored in state instead.
For more details on this, read this section of the docs and this answer.
3. Importing axios, but not using it
import axios from 'axios'
This one isn't really an issue (other than an unused import), and might just be preparation for where you're heading. axios gives a much nicer developer experience than XMLHttpRequest (in my opinion) for http requests and will clean up the fetchData function a lot, which will make troubleshooting easier.
I hope this helps a bit, and you're enjoying React. Feel free to follow up on any of these points in the comments or as new questions.