more information on React lifecycle methods - reactjs

I'm actually working on React and I want to consolidate my knowledge on it.
Starting with lifecycle methods:
getDefaultProps:
properties from both getDefaultProps and parent are consolidate here in this.props like that properties now are ready to be consumed by "getInitialState"
getInitialState:
this.props are used to set the state of the component. The component is now ready to be render
componentWillMount:
what can we do inside ?
render:
self explain
componentWillMount:
we can do some actions to clean the component
componentWillMount seems overkill ?
What do you think ?

My answer assumes your bullet after render was meant to be componentDidMount.
The big difference between the two
componentWillMount is called before the component renders. Anything that needs to be done before rendering should exist in this function (initial calls to retrieve data, initialization of internal structures, etc.).
componentDidMount is called after the component has rendered. Since the component is now added to the DOM tree, any additional DOM manipulation can be performed. Perhaps fire off events notifying the rest of the app that the component is rendered or add the element into a non-React DOM tree.

State modification in componentWillMount will not cause additional rendering, so, it is a place for additional state initialization based on passed props. This article describes lifecycle methods: https://facebook.github.io/react/docs/component-specs.html
P.S. And one more article on state initialization, that could be useful, since you mentioned initializing state from props: https://facebook.github.io/react/tips/props-in-getInitialState-as-anti-pattern.html

Related

Why are browser api event subscribed to in componentDidMount in React?

In this talk https://reactjs.org/docs/hooks-intro.html the speaker write codes that resemble this :
class SomeComponent extends React.Component {
constructor(props){
super(props)
this.handleResize.bind(this)
}
handleResize(){
//do something with window.innerWidth
}
componentDidMount(){
window.addEventListener('resize',this.handleResize)
}
}
Why is the window.addEventListener part in componentDidMount ? Does it have to be ?
From the tone of the talk, I felt that this situation was pretty common.
I'm fairly new to react, and I would have put the browser api event subscription in the constructor just as well.
Is there any advantage that would have elude be as to why put this window.addEventListener in componentDidMount ? Or is it juste for readability purposes ?
To me it's quite simple.
First, you only want api call or event listeners to be called/initialised only once, componentDidMount() and constructor is guaranteed to run only once per mounted component.
However, I won't put api in constructor because if you want a UI update after your data is returned from the api, you need a state change, while you cannot set state in constructor. The only place that only run once and allow you to setState is componentDidMount().
For Event listeners I think it can be put in constructor/componentDidMount. However, the official docs do recommend that to be put in componentDidMount(). Have a look at this.
componentDidMount is called after the component is mounted and has a DOM representation. This is often a place where you would attach generic DOM events.
In general, constructors must not have any side effects.
And also React documentation already mentioned this:
Avoid introducing any side-effects or subscriptions in the constructor. For those use cases, use componentDidMount() instead.
The window.addEventListener define in the componentDidMount life cycle, because code defined inside componentDidMount is executed after the DOM have been rendered. And that would be the right moment to try to attach any event handler to element which is part of the DOM.
But if you did so inside constructor, there are many chance for that to be called before the DOM had been rendered completely.
Read more here
There are multiple reasons about componentDidMount()
In practice, componentDidMount is the best place to put calls to fetch data, for multiple reasons.
1- If you want to subscribe and unsubscribe your function then you need to call that function in componentDidMount() and to unsubscribe(after all operation) call in componentWillUnmount()
2-Using didMount makes it clear that data won’t be loaded until after the initial render. This reminds you to set up initial state properly, so you don’t end up with undefined state that causes errors.
3-componentDidMount() lifecycle method is called after render() to make sure successful DOM loading.
window.addEventListener('resize',this.handleResize)=>
You can call in constructor as well but later if you need to
unsubscribe, can't do because it's initial phase(called initially
only).

How does react decide to rerender a component

I know React has a life cycle method called shouldComponentUpdate, Which by default return true and that's how the component decides to update
But How does that life cycle method gets called, When a state or props change for that component. What actually happens when we receive new props or state? When We connect a component to redux state and mapStateToProps, Are we checking for a change in values inside the component? If not, When We are looking for a change in state or props?
when the props or state changes, how the life cycle methods are called?. Do we have a listener that calls these methods when the props or state changes?
You should look at lifecycles of both, how they perform and in what order each method gets called. Looking at react lifecycle image bellow you can see the difference between componentWillMount and componentDidMount and others like componentDidUpdate, componentWillUpdate and so on...
Also you should reason when to use each method
To update state you call this.setState() which tells react that something has changed and it will re-render component tree. If you use this.state.data = something react won't trigger render(). Now to update props, you need to understand how render() actually works. This answer is summarized from existing anwser already:
Every time render() is called react will create a new virtual DOM
where the root node is the component whose render function is called.
The render() function is called when either the state or the props of
a component or any of its children change. The render() function
destroys all of the old virtual DOM nodes starting from the root and
creates a brand new virtual DOM.
In order to make sure the re-rendering of components is smooth and
efficient React uses the Diffing Algorithm to reduce the time it takes
to create a new tree to a time complexity of O(n), usually time
complexity for copying trees is > O(n^2). The way it accomplishes this
is by using the "key" attribute on each of the elements in the DOM.
React knows that instead of creating each element from scratch it can
check the "key" attribute on each node in the DOM. This is why you get
a warning if you don't set the "key" attribute of each element, React
uses the keys to vastly increase its rendering speed.
React Lifecycle
Redux Lifecycle
If you use redux library, may be, your component does not re-render after your props changes. Checkout this issue to resolve the props changes problem with componentWillReceiveProps

Will componentWillMount run again if component is re-rendered because of parent component?

Will componentWillMount run again if component is re-rendered because of parent component?
No, componentWillMount is called only once.
Also, componentDidMount is called only once.
componentDidUpdate is called on every re-render.
To correctly understand about the react lifecycle methods you can go through this link.
https://engineering.musefind.com/react-lifecycle-methods-how-and-when-to-use-them-2111a1b692b1
The short answer is NO
It's called once right before your component is about to be rendered to the DOM.
The long answer is:
componentWillMount
Your component is going to appear on the screen very shortly. That chunky render function, with all its beautifully off-putting JSX, is about to be called.
Most Common Use Case: App configuration in your root component.
Can call setState: Yes, but don't. Use the default state instead.
componentDidMount
Here is where you load in your data. ComponentDidMount is also where you can do all the fun things you couldn’t do when there was no component to play with. Basically, here you want to do all the setup you couldn’t do without a DOM, and start getting all the data you need. Most Common Use Case: Starting AJAX calls to load in data for your component.
componentWillReceiveProps
Perhaps some data that was loaded in by a parent component’s componentDidMount finally arrived and is being passed down. Before our component does anything with the new props, componentWillReceiveProps is called, with the next props as the argument.
shouldComponentUpdate
shouldComponentUpdate should always return a boolean — an answer to the question, “should I re-render?” Yes, little component, you should. The default is that it always returns true. It's an awesome place to improve performance.
componentWillUpdate
Most Common Use Case: Used instead of componentWillReceiveProps on a component that also has shouldComponentUpdate (but no access to previous props). It’s basically the same as componentWillReceiveProps, except you are not allowed to call this.setState.
componentDidUpdate
Here we can do the same stuff we did in componentDidMount — reset our masonry layout, redraw our canvas, etc. Basically, we use it when it's all said and done, but we don’t want to waste time to redraw the canvas every time it updates. Most Common Use Case: Updating the DOM in response to prop or state changes.
componentWillUnmount
Here you can cancel any outgoing network requests, or remove all event listeners associated with the component. Basically, clean up anything to do that solely involves the component in question — when it’s gone, it should be completely gone.

It's a good pattern to put function in a ReactJS state?

I don't feel right to store a function in a reactjs state, but not sure any disadvantage? Could anyone help analyze it?
view1: function() {
return <div>view1</view>
}
view2: fucntion() {
return <div>view2</view>
}
goView1: function() {
this.setState({contentView: view1})
}
goView2: function() {
this.setState({contentView: view2})
}
render: function () {
return(
{this.state.contentView()}
)
}
There're a few common gotchas about state in react:
Don't mutate state directly, use setState instead
Don't use state when not referenced in render, use instance variable instead.
Well, it seems fine to use state as function, since it's used in your render function to return what to render? Alright, it might not be an anti-pattern, but a better place to put those functions might be in your props, aka render prop, a few reasons:
Think state as your component's data model.
Data are not stale, it changes over time, it could be results from async operations, ui states after user interactions, controlled forms values etc.
Just like redux stores your app's global state, react state should store your component's local state that changes over time, while functions most of time, does nothing more than deferring execution.
Render props is different, it offers IoC (Inversion of Control) for free.
Props most of time similar to local state, should be concerned with UI rendering. However, unlike state owned/managed by component itself, props are passed from parents/clients of the component.
Event handlers for example, event target (usually DOM elements like button, input etc) doesn't need to know how to handle events when creating the component, instead it yields control back to component client/consumer who might need to use setState in its handleEventName handler to update certain container's state shared across children.
Some library (e.g., react router4) also shifted from HOC to render props (e.g., react 16.3 new context API - provider/consumer pair) in favor of its flexibility and explicitness. Instead of composing HOCs before runtime for static version of final enhanced component, you can declare what to render using render props and composing them at runtime in render functions. Thus, you get a clear separation between data (state/props) provider and consumer (where render props are passed from).
Regarding any performance (re-render) concerns, i think it's totally fine to use state as function, since most performance tricks are done by using shouldComponentUpdate hook with shallow compare state/props references (e.g. React.PureComponent, Redux Connect etc), so it's where immutability and memoization comes into play.

React - how to use the lifecycle methods

I keep encountering the same problem with React. I feel I should be using the lifecycle methods. (Other than just componentWillMount and componentWillReceiveProps). But they never seem to meet my purpose. Here are 2 examples:
Asynchronous loading
My parent component loads some data with AJAX. A grandchild component needs this data - which is passed down via props. Because of the timing the data may be available when the child component is mounted or not. I don't know whether to put the code in my grandchild component which depends on these props in componentWillMount() or in componentWillReceiveProps(). I end up having to put it in both. (Or in a method they both call).
Lifecycle methods are either called on the initial render or not. I want them to be called on both.
My component gets some data. (Using getStateFromFlux - a mixin provided by Fluxxor). This occurs several times during the cycle of loading the data with various flags set onto the retrieved data object: unloaded, loading and loaded let's say. This change of state causes a re-render.
I only want to render and show the data if there is something to show. So - my render method has the first line:
if data.loadState != 'loaded'
return '<span />'
Ok. Well. I thought - there must be a lifecycle method to fix this. So I've done this:
shouldComponentUpdate: function (nextProps, nextState) {
if nextState.loadState == 'loaded'
return true
else
return false //stops the render. Good.
}
At last I thought - I have used a lifecycle method.
But, alas, while this does stop the render being called in some cases - when there is no data - I still can't remove the hacky looking line about
if data.loadState != 'loaded'
return '<span />'
This is because shouldComponentUpdate is not called for the initial render. When this component first renders there is no data. loadState is 'unloaded'. The render method is still called. And I still need to avoid displaying the UI (with empty data fields).
In general terms - the lifecyle methods are either called only on the initial render or only on subsequent renders. For most of my uses cases this is singularly unhelpful. I want a method which is agnostic to whether it is the first render or a subsequent one.
What am I missing about React? (The only thing I can think of is is that it is designed to be used with an initial render server-side when you can be sure of your data - then once in the browser the lifecycle methods are about detecting changes).
Thanks
Don't know about loading but with unloading I would suggest;
if (this.props.data.loadstate == 'unloaded') return null;
Have that as the first line of the render. As you noted shouldComponentUpdate only applies to updates.
You're right that you should be using the lifecycle methods, they're awesome and let you hook into your components in a much more in depth way. But I don't think this is the case for your current situation
You could just conditionally render the grandchild only when the data is loaded by the parent and passed to the child. Then you'd only need the check in the child. It would look something like this:
// Child render method that has been passed data loaded by the parent
render: function() {
var grandChild = null;
if (this.props.data) {
grandchild = <GrandChild data={this.props.data} />
}
return (
<div>
{grandchild}
</div>
)
}
In this case, you only pass a data prop to the child component once the data has loaded. Thus, you're guaranteed that when the grandchild component does render, it will have the data that it needs. Although I'm not sure why you are so averse to displaying empty data fields, this should solve the problem.
You're correct, there is no React lifecycle method that fires regardless of whether it's the initial render or not. That being said, if you have to do both, you can always a combination of componentDidMount and either componentDidUpdate or componentWillReceiveProps. I'm not 100% sure why they did this, but a couple reasons that come to mind:
Ensures that React will not need to re-render a component before the initial render (ie. changing state in componentWillReceiveProps, triggering an update before the initial render). I'm not too familiar with the code-base, but I can easily see that causing problems.
Performance boost for the initial render to let your content load faster while the virtual DOM is initialized
I hope this helps solve your problem and sheds some light on the lifecycle methods!

Resources