All articles I've read on React show the code when I should explicitly call this.setState() to trigger DOM update. This seems to be manual triggering of change detection. I call this.setState, React re-renders Virtual DOM and then compares it with the native DOM for changes - if anything changed, the DOM is updated. Here is the quote from the docs:
4) Every second the browser calls the tick() method. Inside it, the
Clock component schedules a UI update by calling setState() with an
object containing the current time. Thanks to the setState() call,
React knows the state has changed, and calls render() method again
to learn what should be on the screen.
Compare it with Angular digest cycle which automatically checks for binding changes and updates DOM. Although I have a way to trigger manual changed detection for a component, it's usually not needed.
My question is whether there are any cases when React triggers DOM update without requiring me to call this.setState() manually, i.e. automatic virtual DOM update?
React is a state machine that maintains a virtual representation of the DOM in memory, which automatically updates/renders (where appropriate) when this state changes.
The reason you see setState being called to trigger a rerender is because this is the most common (only?) means of updating the data structure that feeds this internal DOM representation (which will in turn feed down through the properties of children).
It's not that setState is a manual call to rerender, it's that setState causes the state to change, which in turn causes React to run a diff and update where appropriate. It's all about cascading the data to reflect the current state of your application. If that state hasn't changed then there's nothing to update, and therefore no need to rerender.
This is also why it's a very bad idea to mutate the DOM out from under React, as this more often than not results in a loss of parity between React's virtual representation of the DOM and the actual DOM.
Try not to think about React data bindings in terms of Angular bindings, rather think about it in terms of emulating what Angular bindings do within the context of step-by-step state changes.
Related
I'm working on a Stencil JS project, that makes some network calls to get data and update state.
In React JS, a network call would be done in componentDidMount lifecycle method, and not in componentWillMount method.
I'm surprised to find almost the opposite recommendation in the Stencil docs:
componentWillLoad() Called once just after the component is first connected to the DOM. Since this method is only called once, it's a
good place to load data asynchronously.
Stencil favors componentWillLoad over componentDidLoad in another case too. It logs out console warnings when using componentDidLoad to update state:
STENCIL: The state/prop "exampleProp" changed during "componentDidLoad()", this triggers extra re-renders, try to setup on
"componentWillLoad()"
Why does Stencil push users to componentWillLoad method (before render), while React pushes users to componentDidMount method (after render)?
To start off I don't know much about React but I saw that componentWillMount was deprecated with the following explanation.
There is a common misconception that fetching in componentWillMount lets you avoid the first empty rendering state. In practice this was never true because React has always executed render immediately after componentWillMount. If the data is not available by the time componentWillMount fires, the first render will still show a loading state regardless of where you initiate the fetch. This is why moving the fetch to componentDidMount has no perceptible effect in the vast majority of cases.
In Stencil you can return a Promise in componentWillLoad which will prevent the component from rendering until that Promise has resolved (but I never found a practical use-case for this).
If you don't return a Promise then depending on the speed of the your render method (any possibly other render lifecycle methods) componentDidLoad will run slightly later, which will probably be minimal most of the time (i.e. "no perceptible effect") but without any advantage (that I can think of).
componentDidLoad is meant for things that have to run right after the first render.
Similarly the console warning is because most of the time it doesn't make sense to synchronously modify a #State() or #Prop() property in componentDidLoad as it can often be easily moved to an earlier lifecycle method (avoiding a re-render just after the initial render). There are exceptions though, e.g. if the state value depends on the generated DOM, in that case you can ignore the warning.
Note that in some cases connectedCallback might be even more appropriate than componentWillLoad e.g. the clock example in Stencil's Life Cycle Methods docs.
So I know somethings about vue's life cycle hooks but for some of them I can't think of any real world use case or example that should be done in them and I think it might help me to better understand them by finding out their use case.
here is what I know and don't know about them:
Creation Hooks
beforeCreate(): events and lifecycle have been initialized but data has not been made reactive --- use case ??
created(): you have access to data and events that are reactive but templates and virtual DOM have not yet been mounted or rendered --- use case: API calls
Mounting Hooks
beforeMount(): runs before the initial render --- use case ??
mounted(): you have access to the reactive component, templates and rendered DOM --- use case: modifying the DOM
Updating Hooks
beforeUpdate(): runs after data changes and before the DOM is re-rendered --- use case ??
updated(): runs after data changes and the DOM is re-rendered --- use case ??
Destruction Hooks
beforeDestroy(): runs before tear down --- use case: clean ups to avoid memory leak
destroyed(): runs after tear down --- use case ??
Thanks in advance to anyone helping me to understand these concepts better ;)
According to official VueJS website:
Each Vue instance goes through a series of initialization steps when it’s created - for example, it needs to set up data observation, compile the template, mount the instance to the DOM, and update the DOM when data changes. Along the way, it also runs functions called lifecycle hooks, giving users the opportunity to add their own code at specific stages.
Having that in mind, we have:
beforeCreate
The beforeCreate hook runs at the very initialization of your component. data has not been made reactive, and events have not been set up yet.
Usage
Using the beforeCreate hook is useful when you need some sort of logic/API call that does not need to be assigned to data. Because if we were to assign something to data now, it would be lost once the state was initialized.
created
You are able to access reactive data and events that are active with the created hook. Templates and Virtual DOM have not yet been mounted or rendered.
Usage
Using the created method is useful when dealing with reading/writing the reactive data. For example, if you want to make an API call and then store that value, this is the place to do it.
The above are famously called as creation hooks, as opposed to mounting hooks.
Mounting hooks are often the most used hooks. They allow you to access your component immediately before and after the first render. They do not, however, run during server-side rendering.
beforeMount
The beforeMount hook runs right before the initial render happens and after the template or render functions have been compiled.
Usage
This is the last step you should perform your API calls before it’s unnecessary late in the process because it’s right after created — they have access to the same component variables.
mounted
In the mounted hook, you will have full access to the reactive component, templates, and rendered DOM (via this.$el).
Usage
Use mounted for modifying the DOM—particularly when integrating non-Vue libraries.
There also some hooks, which are called updating hooks.
Updating hooks are called whenever a reactive property used by your component changes or something else causes it to re-render. They allow you to hook into the watch-compute-render cycle for your component.
Use updating hooks if you need to know when your component re-renders, perhaps for debugging or profiling.
There are:
beforeUpdate
The beforeUpdate hook runs after data changes on your component and the update cycle begins, right before the DOM is patched and re-rendered.
Usage
Use beforeUpdate if you need to get the new state of any reactive data on your component before it actually gets rendered.
updated
The updated hook runs after data changes on your component and the DOM re-renders.
Usage
Use updated if you need to access the DOM after a property change
And last but not least, there are destruction hooks.
Destruction hooks allow you to perform actions when your component is destroyed, such as cleanup or analytics sending. They fire when your component is being torn down and removed from the DOM.
There are:
destroyed
By the time you reach the destroyed hook, there’s practically nothing left on your component. Everything that was attached to it has been destroyed.
Usage
Use destroyed if you need do any last-minute cleanup or inform a remote server that the component was destroyed
beforeDestroy
beforeDestroy is fired right before teardown. Your component will still be fully present and functional.
Usage
Use beforeDestroy if you need to clean-up events or reactive subscriptions.
This is the stage where you can do resource management, delete variables and clean up the component.
Keep in mind that these are the main lifecycle hooks and there are some other minor ones such as activated and deactivated that you can look into.
Here is a link that might help you further down the line.
I am learning React, and trying to wrap my head around the syntax, and concepts. From the tutorials of React it is mentioned:
State Updates May Be Asynchronous
React may 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.
My question is, if the this.state is not updated at all times, can we rely on it to show the right information? If my understanding is correct, React will update this state in batches for performance reasons, but does it affect the accuracy of the application? How does React create these batches and when do they get applied?
React uses state to help manage each piece of component with javascript. Since state can always change it makes it really flexible. One downside is that since it is flexible it can be hard to manage the state when there are multiple objects. It is ideal to keep components in manageable pieces so that you can locate when a state is not behaving as expected.
To prevent data from mutating unexpectedly, tools/concept such as ImmutableJs or Redux have been combined with React to make managing tools more efficent.
Redux controls/organizes where pieces of state changes through a one-directional flow. http://redux.js.org/docs/basics/UsageWithReact.html
ImmutableJs uses persistent immutable data structures which locks state to prevent unexpected changes. https://facebook.github.io/immutable-js/
React will render component with updated state as soon as it is reasonable - for example in event handlers you are able to change state of multiple components, however it is not reasonable to render them with new state separately - instead React will batch updates and render components after event handler finishes.
In correctly written application delay between update and render will be unnoticeable for user. From developer perspective asynchronous updates may introduce hard-to-find bugs (using Redux where every state update is based on previous state should solve most of them; this is of course possible also in pure React by using setState() with callback).
State being asynchronous does not mean that you can't rely on it, but you should be careful how and when you are using the information you are keeping there.
For example:
this.setState({charCount: 5});
console.log(this.state.charCount) // may not be 5 as setState is asynchronous
On the other hand you can use callback to be sure that you got a correct value:
this.setState({charCount: 5}, () => { console.log(this.state.charCount) });
General practice is that you should try to minimize the use of state and only use it, when changes are needed on user interface. If you need to process or manipulate data without UI changes try to avoid using state and use for example this practice: Lifting State Up
It is my understanding that you are not supposed to change states in the render function cause that would cause and infinite re render or the component.
This makes perfect sense, but I find myself in a particular situation. I am building an offline application and I am using an offline storage system to retrieve data. Now, whenever a method is called to get certain data, cache is checked, if it is not expired the component will be able to access the data and therefore nothing happens, but if it is expired there is a call to the API, the data is updated and the interested components re-rendered.
These methods will change the state of the component the first time they are called because they are going to the API grabbing the new data and re-rendering, and then they will not change the state anymore because the data will already be in cache.
Now, I could call these methods in component will mount, and that is what I am doing now, but if I am forced to re call them, I need to unmount and remount the components. Is this the only possible way of doing this?
Thanks!
Well the first step is understanding that state management and rendering needs to be decoupled which you got already.
Now what you can do is consider your external state/cache element as an observable object (ie. I want to do something like observableObject.listen('change', onChangeHandler); you can use EventsEmitter from the events library). You do that listening on componentDidMount and clean up in componentWillUnmout. That onChangeHandler is very simple: this.setState({ value: observableObject.value }) which will trigger a component re-render which should be a pure function that outputs DOM nodes depending on props being passed and it's own state.
This means that your logic of checking if the cache is invalid is not on a per request of the value (inside rendering) but rather think of the object as self contained. It regularly checks if itself needs to notify its listeners that it changed. Since JS does not do parallel execution you don't have to deal with threads and synchronization. You know that at the point in time your render function executes it will have the latest value. If after rendering the logic that checks for cache executes and it sees that it needs to be updated it simply notifies as said earlier its listeners and that makes your component re-render because your onChangeHandler changed the state.
Hope I helped.
I saw this line as an answer to another question on here:
"componentWillMount should be componentDidMount, or else you'll leak event emitters in node."
and I don't really understand it. Can someone explain with more detail?
More info:
Building a react application with flux, as part of the initial render, a child component computes some data. Ideally, after this data is computed, I would like to call an action that updates the store's state with a portion of this new data.
Normally, updating the store's state emits a change event that causes a re-render. However, because the change listener isn't being added until componentDidMount (rather than in componentWillMount), my top level component isn't able to listen for the change that occurs during the initial render and initiate a re-render.
If I move the addChangeListener to componentWillMount that would seem to fix this issue, but the above quote suggests that this is a bad idea?
I think the prevailing wisdom that listeners should be set in componentDidMount because it prevents problems in isomorphic applications is a mistake. I think in 98% of cases for non-isomorphic applications setting listeners in either componentWillMount and componentDidMount will work the same way, but it is conceptually wrong and in the 2% of cases (such as the example given in the original question) it will do the wrong thing.
There are git issue discussions and comments in the React source code suggesting that it would be preferred that componentWillMount wasn't called on the server at all, but if it isn't then problems are created in the checksum test comparing the server prerender to the client initial render. Having componentWillMount on the server means that it isn't executed as part of the component lifecycle in this case, but this is being used as an excuse to not count it as part of the lifecycle in any case.
In fact, componentWillMount is exactly the right place to register listeners if you are not creating an isomorphic application. If you are creating an isomorphic application then you have to make some compromises due to the checksum/lifecycle issue not being ideal in this case (maybe just testing for the server environment and then not registering listeners?).
In non-isomorphic applications adding listeners in componentWillMount can save unnecessary re-renders in some cases and will register them in document order. The advantage of document order is that if you have a way to flush pending events as components are re-rendered (for example, takeRecords on a MutationObserver) then you can ensure the document is re-rendered top down instead of bottom up, converting the rendering complexity to linear from polynomial.
Additionally, there is no danger period between the initial render and when the listener is registered where the Store can change without triggering a render, causing the view to be out of sync with the Store (the example problem given in the original question). If the listener is registered in componentDidMount you either need to make sure the Store isn't changed in componentDidMount calls in children, or else force a re-render/re-sync after registering the listener, which if done in componentDidMount is done in reverse document order which may be polynomial complexity (depending on how/if the React setStates are aggregated).
Is hard to understand what that quote means without more context. What I can tell you is that there are huge differences between the two of those methods.
On one hand, componentWillMount is called before the component is actually added to the DOM. This is the last chance you have to update component's state and get it rendered before the component is rendered by the browser.
On the other hand, componentDidMount is called once the component has been attached to the DOM (the real one).
What you need really depends on your use case. In general, componentDidMount is used to integrate with other libraries (like jQuery), it provides a way to modify the HTML rendered by the component.
I suggest you to read these links:
https://facebook.github.io/react/docs/component-specs.html#mounting-componentwillmount
https://facebook.github.io/react/docs/component-specs.html#mounting-componentdidmount
https://facebook.github.io/react/tips/use-react-with-other-libraries.html