情景描述
-
需求:
- 父組件需要在初始化的時(shí)候發(fā)送請(qǐng)求獲取一個(gè)userId的數(shù)組
- 父組件需要把獲取到的這個(gè)數(shù)組傳遞給子組件
- 子組件需要在初始化的時(shí)候?qū)Ω附M件傳入的數(shù)組做循環(huán)骄噪,循環(huán)使用userId發(fā)送請(qǐng)求獲取user信息
- 子組件將獲取到的所有user信息使用列表展現(xiàn)出來
-
實(shí)現(xiàn):
- 在父組件的
componentDidMount
中發(fā)送請(qǐng)求獲取到userId數(shù)組 - 傳遞給子組件
- 在子組件的
componentDidMount
中循環(huán)發(fā)送請(qǐng)求獲取user信息
- 在父組件的
-
出現(xiàn)問題:
- 發(fā)現(xiàn)子組件拿到的userId數(shù)組始終未空
解析
Q1:包含父子組件的生命周期經(jīng)歷了怎樣的過程
-
A1: 假設(shè)有這樣的組件結(jié)構(gòu)
class Father extends Component{ componentDidMount(){ console.log('father componentDidMount') } render(){ console.log('father render') return ( <div> <Children1 /> <Children2 /> </div> ) } } class Children extends Component{ componentDidMount(){ console.log('children componentDidMount') } render(){ console.log('children render') return ( <h1>這是子</h1> ) } }
掛載階段的執(zhí)行順序:
- 1.父類的ComponentWillMount
- 2.父類的render
- 3.子類1的ComponentWillMount
- 4.子類1的render
- 5.子類2的ComponentWillMount
- 6.子類2的render
- 7.子類1的ComponentDidMount
- 8.子類2的ComponentDidMount
- 9.父類的ComponentDidMount
得出結(jié)論:
- 父類的componentDidMount必須在所有子類的ComponentDidMount之后執(zhí)行
- 并行子類:先依次執(zhí)行并行組件的render方法知道最后一個(gè)子類的render執(zhí)行完,再開始從第一個(gè)子組件依次執(zhí)行ComponentDidMount方法
- 錯(cuò)誤原因:
- 因?yàn)楦割惖腃omponentDidMount比子類的晚茄菊,因此父類子類發(fā)請(qǐng)求的時(shí)候父類還沒有發(fā)請(qǐng)求拿到userId數(shù)組,這時(shí)候子類拿到的所有數(shù)據(jù)都是undefined
- Q2:如何能做到讓父類的ComponentDidMount先于子類執(zhí)行呢箕肃?這樣是不是可以解決這個(gè)問題呢茉帅?
- A2:首先這樣想問題的出發(fā)點(diǎn)就是錯(cuò)的
-
父子的生命周期函數(shù)的調(diào)用都是同步的
- 就算父的ComponentDidMOunt先執(zhí)行,ComponentDidMOunt中你發(fā)了請(qǐng)求
- 請(qǐng)求需要時(shí)間
- 而子類的componentDidMount并不會(huì)等待父類的異步請(qǐng)求執(zhí)行完畢之后再執(zhí)行
-
- Q3:父類傳給子類的值是否子類的任何一個(gè)生命周期函數(shù)都能拿到呢涨冀?
- A3:答案是肯定的,子類可以在自己的任何一個(gè)生命周期函數(shù)中拿到父類傳入的數(shù)據(jù)
- Q4:可不可以在子類使用componentWillReceiveProps判斷父類數(shù)據(jù)一旦請(qǐng)求到子類立刻發(fā)送請(qǐng)求
- A4:這樣是好的解決方法麦萤,而由于我之前對(duì)componentWillReceiveProps的錯(cuò)誤理解拒絕使用鹿鳖,誤區(qū)如下
- 拒絕在所有的will生命周期函數(shù)中setState,所以也就不愿意在其中發(fā)請(qǐng)求
-
componentWillReceiveProps只會(huì)在props類型數(shù)據(jù)發(fā)生改變的時(shí)候調(diào)用壮莹,state屬性發(fā)生改變永遠(yuǎn)不會(huì)觸發(fā)
-
- 害怕componentWillReceiveProps會(huì)執(zhí)行很多次出現(xiàn)請(qǐng)求很多次的情況
-
componentWillReceiveProps函數(shù)處理數(shù)據(jù)的時(shí)候一定要加上判斷翅帜,并且判斷條件要考慮到兩方面
- 第一次可以執(zhí)行
- 以后不能再執(zhí)行
-
- 拒絕在所有的will生命周期函數(shù)中setState,所以也就不愿意在其中發(fā)請(qǐng)求
我的解決方案
- 父類ComponentDidMount發(fā)請(qǐng)求
- render中判斷數(shù)據(jù)是否拿到
- 拿到之后再掛載子類組件
- 并且為了保證如果當(dāng)前組件被封成一個(gè)Component之后其他人能夠正常使用
- 因此根據(jù)無狀態(tài)組件的特點(diǎn)
- 在當(dāng)前組件的外層封裝無狀態(tài)組件(用來根據(jù)數(shù)據(jù)是否獲取確定組件的加載時(shí)機(jī))
- 這時(shí)候直接在父類中引入這個(gè)無狀態(tài)組件
- 保證父類不會(huì)知道這個(gè)組件被延遲加載
其他解決方案
- 父組件仍然在componentDidMount里面發(fā)送請(qǐng)求
- 子組件在componentWillReceiveProps中判斷數(shù)據(jù)是否存在
- 存在的話就在子類的componentWillReceiveProps中發(fā)送請(qǐng)求