Why we should Avoid using UNSAFE componentWillMount, componentWillReceiveProps, componentWillUpdate

 

Avoid using UNSAFE componentWillMount (UNSAFE_componentWillMount)


Avoid using UNSAFE componentWillMount, componentWillReceiveProps, componentWillUpdate

Using componentWillMount for init state ?

We can using `state initialization` or init state in constructor => we don't need using componentWillMount

import React from "react";
class ExampleComponent extends React.Component {
state = {
currentColor: this.props.defaultColor,
palette: "rgb"
};
}

class ExampleComponent2 extends React.Component {
constructor(props) {
super(props);
this.state = {
currentColor: this.props.defaultColor,
palette: "rgb"
};
}
}

Using componentWillMount for fetching external Data ?

import React from "react";
class ExampleComponent extends React.Component {
state = {
externalData: null,
};

componentDidMount() {
this._asyncRequest = loadMyAsyncData().then(
externalData => {
this._asyncRequest = null;
this.setState({externalData});
}
);
}

componentWillUnmount() {
if (this._asyncRequest) {
this._asyncRequest.cancel();
}
}

render() {
if (this.state.externalData === null) {
// Render loading state ...
} else {
// Render real UI ...
}
}
}

You want to fetch exteral data to avoid empty rendering state => You were wrong!
React has always executed `render` immediately after `componentWillMount`. Therefore, when fetching external data has not completed yet, the `render` method had been called
Futhermore, If your app is Server Side Rendering, componentWillMount will be called twice

=> We need use componentDidMount for fetching external data. componentDidMount will be called only once.

Using componentWillMount for event listeners ?

class ExampleComponent extends React.Component {
componentWillMount() {
this.setState({
subscribedValue: this.props.dataSource.value,
});
// This is not safe; it can leak!
this.props.dataSource.subscribe(
this.handleSubscriptionChange
);
}

componentWillUnmount() {
this.props.dataSource.unsubscribe(
this.handleSubscriptionChange
);
}

handleSubscriptionChange = dataSource => {
this.setState({
subscribedValue: dataSource.value,
});
};
}

The code above cause memory leaks for server in case server side rendering because in server side rendering the componentWillUnmount will never called.
The code above cause memory leaks in browser IN CASE the rendering might be interrupted before it completes => componentWillUnmount not to be called.

=> We need using componentDidUpdate for register listeners

Avoid using UNSAFE componentWillReceiveProps (UNSAFE_componentWillReceiveProps) ?

class ExampleComponent extends React.Component {
state = {
isScrollingDown: false,
};

componentWillReceiveProps(nextProps) {
if (this.props.currentRow !== nextProps.currentRow) {
this.setState({
isScrollingDown:
nextProps.currentRow > this.props.currentRow,
});
}
}
}

The code above is valid. But if someone use componentWillReceiveProps like:

import React from "react";
class ExampleComponent extends React.Component {
state = {
isScrollingDown: false,
};

componentWillReceiveProps(nextProps) {
this.setState({
isScrollingDown:
nextProps.currentRow > this.props.currentRow,
});
}
}

In this case, Any props change will make setState

=>  the componentWillReceiveProps lifecycle is often mis-used in ways that do present problems. We need to determine what condition we can using setState in componentWillReceiveProps and what the condition we cannot using setState in componentWillReceiveProps
=>  the componentWillReceiveProps will be deprecated.
=> As of version 16.3, the recommended way to update state in response to props changes is with the new static getDerivedStateFromProps lifecycle

Avoid using UNSAFE componentWillUpdate (UNSAFE_componentWillUpdate) ?

componentWillUpdate may be called multiple times for single update. If we call external callback in 
componentWillUpdate, the external callback may be called multiple times

class ExampleComponent extends React.Component {
componentWillUpdate(nextProps, nextState) {
if (
this.state.someStatefulValue !==
nextState.someStatefulValue
) {
nextProps.onChange(nextState.someStatefulValue);
}
}
}

=> the componentDidUpdate lifecycle should be used since it is guaranteed to be invoked only once per update


References:




Nhận xét

Bài đăng phổ biến từ blog này

TypeORM should using repository or query buider ?

Type of children prop in React Typescript