React過時(shí)的生命周期 2019-09-23

最近調(diào)試React項(xiàng)目的時(shí)候,控制臺老是輸出一些警告信息,比如這樣的

1569207926863.jpg

警告componentWillMount、componentWillReceiveProps已被重命名,并且原生命周期將在React 17.x版本失效。而其提供的鏈接,不翻墻也打不開。

關(guān)于即將過時(shí)的生命周期,總共有三個(gè)componentWillMount、componentWillReceiveProps以及componentWillUpdate,目前來說(React 16.9.0),這些方法仍然有效,但不建議在新代碼中使用它們。

其實(shí)在16.3版本,就已經(jīng)提供了相應(yīng)的重命名生命周期,以UNSAFE_開頭,舊的生命周期函數(shù)與新的同時(shí)生效;在16.9版本中開啟了dev警告,未來將在React 17.x版本中完全棄用,只有新的UNSAFE_生命周期名稱將起作用。

在這里,UNSAFE_不是指安全性,而是表示使用這些生命周期的代碼在React的未來版本中更有可能出現(xiàn)錯(cuò)誤,尤其是在啟用異步渲染后。

解決方案

1、直接更改為新的生命周期函數(shù)

將代碼中的componentWillMount、componentWillReceiveProps、componentWillUpdate函數(shù)全部加上UNSAFE_前綴,替換成

UNSAFE_componentWillMount()
UNSAFE_componentWillReceiveProps(nextProps)
UNSAFE_componentWillUpdate(nextProps, nextState)

這樣做就不用更改原代碼邏輯,不存在改完后出現(xiàn)BUG的問題,但是也只是臨時(shí)方案,最終還是要遷移到其他生命周期函數(shù)的,說不定什么時(shí)候UNSAFE_的函數(shù)就被完全拋棄了呢。

如果沒時(shí)間或者要修改的地方太多,想偷下懶的話,可以使用react-codemod腳本自動(dòng)重命名

cd your_project
npx react-codemod rename-unsafe-lifecycles

有時(shí)候可能會出現(xiàn)But before we continue, please stash or commit your git changes.的警告,只需要提交下git代碼或者加上--force強(qiáng)制執(zhí)行。

2、替換為其他生命周期函數(shù)

① componentWillMount -> componentDidMount
componentWillMount()會在render之前被調(diào)用,因此在此方法中同步調(diào)用 setState() 不會觸發(fā)額外渲染,并且通常都是在構(gòu)造函數(shù) constructor()中初始化 state

在大多數(shù)情況下,都可以直接將代碼移至componentDidMount。而在支持服務(wù)器渲染時(shí),當(dāng)前需要同步提供數(shù)據(jù),通常也會在componentWillMount中獲取數(shù)據(jù)(fetching),但可以使用構(gòu)造函數(shù)constructor代替。

有一個(gè)常見的誤解,即在componentWillMount中進(jìn)行獲取數(shù)據(jù),可以避免出現(xiàn)第一個(gè)空渲染狀態(tài)。 實(shí)際上,這是行不通的,因?yàn)镽eact總是在componentWillMount之后立即執(zhí)行render。 如果在componentWillMount觸發(fā)時(shí)數(shù)據(jù)不可用,則無論在何處啟動(dòng)fetching,第一個(gè)渲染器仍將顯示加載狀態(tài)。 這就是為什么在大多數(shù)情況下將數(shù)據(jù)獲取(fetching)移到componentDidMount不會產(chǎn)生明顯影響的原因。

② componentWillReceiveProps -> componentDidUpdate
componentWillReceiveProps()會在已掛載的組件接收新的 props 之前被調(diào)用。如果你需要更新狀態(tài)以響應(yīng) prop 更改(例如,重置它),你可以比較 this.propsnextProps 并在此方法中使用 this.setState() 執(zhí)行 state 轉(zhuǎn)換。

使用此生命周期方法通常會出現(xiàn) bug 和不一致性:

  • 如果你需要執(zhí)行副作用(例如,數(shù)據(jù)提取或動(dòng)畫)以響應(yīng) props 中的更改,請改用 componentDidUpdate 生命周期。
  • 如果你使用 componentWillReceiveProps 僅在 prop 更改時(shí)重新計(jì)算某些數(shù)據(jù),請使用 memoization helper 代替。
  • 如果你使用 componentWillReceiveProps 是為了在 prop 更改時(shí)“重置”某些 state,請考慮使組件完全受控或使用 key 使組件完全不受控代替。

③ componentWillUpdate -> componentDidUpdate
這是一個(gè)組件的示例,該組件在內(nèi)部狀態(tài)更改時(shí)調(diào)用外部函數(shù):

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

有時(shí)人們使用componentWillUpdate是因?yàn)閾?dān)心當(dāng)componentDidUpdate觸發(fā)時(shí),更新其他組件的狀態(tài)“太晚了”。事實(shí)并非如此。React確保在componentDidMountcomponentDidUpdate期間發(fā)生的任何setState調(diào)用在用戶看到更新的ui之前被刷新。一般來說,最好避免像這樣層疊更新,但在某些情況下它們是必要的(例如,如果在測量渲染的dom元素之后需要定位工具提示)。

不管怎樣,在異步模式下為此目的使用componentWillUpdate都是不安全的,因?yàn)橐淮胃驴赡軙啻握{(diào)用外部回調(diào)。相反,應(yīng)該使用componentDidUpdate生命周期,因?yàn)樗WC每次更新只調(diào)用一次:

// After
class ExampleComponent extends React.Component {
  componentDidUpdate(prevProps, prevState) {
    if (
      this.state.someStatefulValue !==
      prevState.someStatefulValue
    ) {
      this.props.onChange(this.state.someStatefulValue);
    }
  }
}

End

參考鏈接:

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容