javascript - react 的問(wèn)題,標(biāo)題不知怎么起...
問(wèn)題描述
我具體描述下問(wèn)題產(chǎn)生的原因吧。現(xiàn)在有三個(gè)組件(暫定a、b、c)去實(shí)現(xiàn)一個(gè)用戶認(rèn)證的功能。a組件是父組件(相對(duì)b、c,a組件外面還有父組件),負(fù)責(zé)接收父組件傳遞下來(lái)用戶的認(rèn)證信息,b組件是用戶用來(lái)填寫(xiě)信息的地方,c組件是表示用戶的認(rèn)證狀態(tài)(未認(rèn)證、審核、已認(rèn)證、認(rèn)證失敗,分別對(duì)應(yīng)狀態(tài)為0,1,2,-1)。假如用戶認(rèn)證失敗了,c組件內(nèi)部會(huì)有一個(gè)按鈕,讓用戶重新認(rèn)證(切換b、c組件)。
我一開(kāi)始寫(xiě)的時(shí)候是這么想的:提取一個(gè)狀態(tài)到a組件中(暫定show),show的值是根據(jù)a組件傳遞下來(lái)的認(rèn)證狀態(tài)(props)來(lái)確定的,通過(guò)show來(lái)改變應(yīng)該展示哪個(gè)組件。當(dāng)用戶認(rèn)證失敗的時(shí)候點(diǎn)擊c組件中的“重新認(rèn)證”,通過(guò)回調(diào)函數(shù)改變父組件show的狀態(tài),完成b、c組件的切換。問(wèn)題就出現(xiàn)在這個(gè)show上(暫定true顯示b組件,false顯示c組件),show的默認(rèn)值為true(讓用戶輸入信息)。我在a組件的componentWillReceiveProps里面去改變show的狀態(tài)(didMount拿不到props,render里面不能操作state)。現(xiàn)在不論用戶是否通過(guò)認(rèn)證了,a組件加載的時(shí)候默認(rèn)展示的都是b組件,因?yàn)閏omponentWillReceiveProps沒(méi)有被調(diào)用。刷新頁(yè)面之后才會(huì)展示c組件。現(xiàn)在我能想到的解決辦法就是讓a組件去拿數(shù)據(jù),然后確定show的狀態(tài)。我想問(wèn)下各位大神,還有更好的辦法幫我實(shí)現(xiàn)這個(gè)功能嗎?
補(bǔ)一張圖吧,看的清楚點(diǎn)
問(wèn)題解答
回答1:a:
//構(gòu)造器內(nèi)this.state = { show:true}//class內(nèi)changeState(){ this.setState({show:false})}//render內(nèi)const c_props = {changeState}<C {...c_props}/>
c:
onclick(){ this.props.changeState();}回答2:
應(yīng)該有一個(gè)組件去決定是否要進(jìn)行用戶認(rèn)證,如果你想讓登錄組件全部包攬這個(gè)邏輯,那你需要一個(gè)加載狀態(tài),剛開(kāi)始的時(shí)候處于加載中,什么都不顯示。所謂加載就是決定是否要認(rèn)證(發(fā)API請(qǐng)求等等),加載完畢后就可以決定是否要認(rèn)證。
didMount拿不到props
我100%保證 componentDidMount() 是可以拿到props參數(shù)的,通過(guò) this.props 獲取,但是componentDidMount() 只在組件創(chuàng)建時(shí)調(diào)用一次,通常情況下如果要加載數(shù)據(jù)就在 componentDidMount() 里執(zhí)行。
回答3:show為什么要是a組件的state?你把show當(dāng)作render函數(shù)中的一個(gè)局部變量就行了。
假定a組件從props里傳遞過(guò)來(lái)的認(rèn)證狀態(tài)變量命名為 auth,你的 a 組件render方法可以這樣寫(xiě):
class A extends Component { render () { let show = this.props.auth === 2; // 0 1 2 -1 return ( <p> {show && <p>component B</p>} {!show && <p>component C</p>} </p> ); }}
========= 更新 =========
第一次沒(méi)看到你的C組件居然還有一個(gè)回調(diào)箭頭來(lái)改變A組件的show!
對(duì),這一步也是錯(cuò)誤的設(shè)計(jì)。
A組件得到的認(rèn)證信息是A組件的父組件傳遞下來(lái)的,那么這個(gè)show就應(yīng)該要唯一依賴于這一個(gè)信息的,C組件具有改變這個(gè)認(rèn)證信息的功能,那么,A組件有義務(wù)把這個(gè)改變通知給A組件的父組件,而不是私自地悄么聲地改變自己組件的state,即你在這里設(shè)定的show這個(gè)state,就草草了事。試想,這個(gè)時(shí)候,A組件得到的props是認(rèn)證失敗,渲染了C組件,C組件有重新認(rèn)證的功能,用戶重新認(rèn)證成功,C組件又通知A組件認(rèn)證成功了,這個(gè)時(shí)候A組件要相信誰(shuí)?props和state就不同步了!更慘的是A組件的父組件,他還傻乎乎地以為自己拿到的是正確的信息,還通過(guò)props告訴A組件,用戶認(rèn)證失敗啦,殊不知A組件已經(jīng)串通他底下的小弟,把認(rèn)證信息都給改了!倘若這個(gè)時(shí)候A組件有個(gè)兄弟叫A2組件,A2也通過(guò)props從他們共同的父組件接收認(rèn)證信息,那就會(huì)出現(xiàn)A和底下一幫家伙悄悄重新認(rèn)證了,而A的父親和兄弟還蒙在鼓里,頁(yè)面顯示就不一致啦!
正確的設(shè)計(jì)是,A組件在接收到C組件重新認(rèn)證成功的事件通知,需要把這個(gè)通知繼續(xù)往上傳遞,告訴A組件的父組件,父組件接收到這個(gè)事件,改變他自己的狀態(tài),進(jìn)而改變傳遞給A組件的props,A組件props改變,導(dǎo)致A組件重繪,從而replace C with B。
認(rèn)證信息只能保存一份,你的例子里,認(rèn)證信息放在A組件的父組件里,因此,要修改這個(gè)認(rèn)證信息,也應(yīng)該在A組件的父組件里完成。因此,這個(gè)show其實(shí)只是一個(gè)根據(jù)props產(chǎn)生的中間變量,根本無(wú)需設(shè)計(jì)成A的state。
如果你用redux就沒(méi)有這個(gè)疑惑了。
