react v16.3 版本的發佈,生命週期函數的變更去掉了如下三個html
同時爲了彌補失去上面三個週期的不足又加了兩個react
過分方案是在以前項目中使用去掉的函數添加前綴 UNSAFE_, 官網提示能夠繼續使用至 React 17。但在項目中依然會有一些waring ,建議修改。如下是項目中一些替換策略,涉及也是比較全面,且有我深刻淺出一一闡述。數組
componentWillMount 函數中的場景有一下種:bash
在此方法中引入任何反作用或訂閱。如遇此種狀況,請改用 componentDidMount()
componentWillReceiveProps 函數在初始的props不會渲染。會在組件接受到新的 props 時調用。通常用於父組件更新狀態時子組件的從新渲染。替換的場景以下:dom
替換策略:異步
若是您須要 執行反作用 (side effect)(例如,數據獲取或動畫)以響應 屬性 (props) 的更改,使用 componentDidUpdate 生命週期方法ide
使用 componentWillReceiveProps, 在屬性 (props) 改變 時從新計算一些數據,請使用 memoization 輔助工具-官網有例子函數
使用 componentWillReceiveProps , 在屬性 (props) 改變時 「重置」 一些 state (狀態),考慮使用一個 徹底控制組件 或 一個 帶 key 的徹底不受控 組件工具
可使用 static getDerivedStateFromProps + componentDidUpdate vs getSnapshotBeforeUpdate + componentDidUpdate性能
以上3種狀況是官網推薦, 也是比較簡單的方式。static getDerivedStateFromProps 函數是官網也不推薦使用的函數,因此命名就比較長, 項目中對對此函數的替換在不拆分組件, 沒有使用hook的狀況下使用第3種策略進行的改寫。
static getDerivedStateFromProps(props, state)
在調用 render 方法以前被調用,包括初始裝載(mount)和後續更新時。 它應該返回一個更新 state (狀態) 的對象,或者返回 null 以不更新任何 state (狀態)。
getSnapshotBeforeUpdate(prevProps, prevState)
在最近一次的渲染輸出被提交以前調用, 它返回的值將做爲第三個 snapshot 參數傳遞給 componentDidUpdate() 。 不然這個參數將是 undefined componentDidUpdate(prevProps, prevState, snapshot)
此方法能夠調用 setState()來操做 DOM 。但請注意,必須包含在條件語句中 像上面的例子同樣,不然你會致使無限循環。 這也會致使額外的從新渲染, 雖然對用戶不可見,可是會影響組件的性能。
例子1更改前
UNSAFE_componentWillReceiveProps(nextProps) {
const { models = [], itemId, shopId } = nextProps.sellerData;
const { itemId: currentItemId } = this.props.sellerData;
if (itemId !== currentItemId && models.length && models.length > 0) {
this.setState(
{
matchShop: {}, // 初始化state
},
// callback 中調用 this.props 中父組件的方法
() => {
this.init(models);
this.props.onGetMatchingTable({
modelid: models[0].model_id,
itemId,
shopId
});
}
);
}
}
複製代碼
例子1更改後
// getDerivedStateFromProps 接收最新的 Props 值 nextProps、上一個 state 值 prevState 兩個參數,返回返回一個對象來更新 state,或者返回 null 表示不須要更新 state。
static getDerivedStateFromProps(nextProps, prevState) {
const { models = [], itemId, shopId } = nextProps.sellerData;
const { itemId: currentItemId } =
(prevState && prevState.preSellerData) || '';
if (
currentItemId !== '' &&
itemId !== currentItemId &&
models.length &&
models.length > 0
) {
return {
matchShop: {},
};
}
return null;
}
componentDidUpdate(prevProps, prevState) {
const { itemId: currentItemId } = prevProps.sellerData;
const { models = [], itemId, shopId } = this.props.sellerData;
if (itemId !== currentItemId && models.length && models.length > 0) {
// console.log('prevState---this.props', this.props, prevState, prevProps);
this.init(models);
this.props.onGetMatchingTable({
modelid: models[0].model_id,
itemId,
shopId
});
}
}
複製代碼
例子2 state狀態中iptUrl 是在子組件中,而且都多處能夠變動,父組件傳值props 用戶能夠輸入url,這種狀況下使用 getDerivedStateFromProps靜態方法就會觸發頁面更改進入死循環。使用getSnapshotBeforeUpdate + componentDidUpdate進行替換修改。
// 更改前註釋狀態
// UNSAFE_componentWillReceiveProps(nextProps) {
// if (nextProps.url !== this.state.iptUrl) {
// this.setState({
// iptUrl: nextProps.url,
// errMsg: ''
// });
// }
// }
// 更改後
getSnapshotBeforeUpdate(prevProps, prevState) {
if (prevProps.url !== this.props.url) {
return this.props.url;
}
return null;
}
componentDidUpdate(prevProps, prevState, snapshot) {
if (snapshot !== null) {
this.setState({ iptUrl: this.props.url, errMsg: '' });
}
}
複製代碼
在React 16.8 版本中可使用 Effect Hook, useEffect Hook 看作 componentDidMount,componentDidUpdate 和 componentWillUnmount 這三個函數的組合。在hook 中沒有生命週期的概念,更改數據的操做均可以稱爲反作用。Effect Hook 可讓你在函數組件中執行反作用操做。