[英]What's the proper way of passing a ref to a prop?
我正在嘗試將一個組件的 ref 傳遞給另一個組件。 由於不推薦使用字符串引用,因此我使用回調引用。
所以我有類似的東西:
<One ref={c => this.one = c}/>
<Two one={this.one}/>
問題是,每當我試圖訪問this.props.one
里面Two
我得到undefined
。
我什至在Two
上試過這個:
componentDidMount(){
setTimeout(()=>{
console.log(this.props.one);
},5000)
}
似乎問題在於,當創建 prop 時,ref 還不存在,因為它是在安裝One
創建的。 但我不知道如何“刷新” Two
上的道具以獲取已安裝組件的引用。
那么將 ref 傳遞給另一個組件的正確方法是什么?
編輯
一些用戶建議將該邏輯封裝在更高的組件中,該組件本身呈現那些其他子組件。
這種方法的問題在於您無法創建可重用的邏輯,並且必須在這些封裝組件中一遍又一遍地重復相同的邏輯。
假設你想創建一個通用的<Form>
組件,它封裝了你的商店的提交邏輯、錯誤檢查等。你做這樣的事情:
<Form>
<Input/>
<Input/>
<Input/>
<Input/>
<SubmitButton/>
</Form>
在這個例子中, <Form>
不能訪問孩子的實例(和方法),因為this.props.children
不返回這些實例。 它返回一些偽組件列表。
那么如何在不傳遞 ref 的情況下檢查某個<Input/>
是否檢測到驗證錯誤?
您必須使用驗證邏輯將這些組件封裝在另一個組件中。 例如在<UserForm>
。 但是由於每個表單都不同,因此必須在<CategoryForm>
、 <GoupForm>
等中復制相同的邏輯。這是非常低效的,這就是為什么我想將驗證邏輯封裝在<Form>
並傳遞<Input>
引用組件到<Form>
。
一般來說,“ref”特性是 React 中的一種反模式。 它的存在是為了支持副作用驅動的開發,但是為了從 React 編程方式中獲得最大收益,您應該盡可能避免“引用”。
至於你的特定問題,將一個孩子傳遞給它的兄弟姐妹是一個雞與蛋的場景。 ref 回調在孩子被掛載時觸發,而不是在渲染期間觸發,這就是您的示例不起作用的原因。 您可以嘗試的一件事是將 ref 推入狀態,然后從狀態讀取到另一個孩子。 所以:
<One ref={c => !this.state.one && this.setState({ one: c })}/>
<Two one={this.state.one}/>
注意:如果沒有!this.state.one
這將導致無限循環。
這是此工作的 codepen 示例(查看控制台以查看記錄的兄弟參考): http : //codepen.io/anon/pen/pbqvRA
現在使用新的 ref api (自 React 16 起可用 - 感謝 perilandmishap 指出這一點)現在要簡單得多。
class MyComponent extends React.Component {
constructor (props) {
super(props);
this.oneRef = React.createRef();
}
render () {
return (
<React.Fragment>
<One ref={this.oneRef} />
<Two one={this.oneRef} />
</React.Fragment>
}
}
}
您將在Two
使用道具,例如:
this.props.one.current
這種方法有幾點值得注意:
ref 將是一個具有current
屬性的對象。 在安裝元素/組件之前,該屬性將為null
。 一旦掛載,它將是One
的實例。 一旦<Two />
被掛載,引用它應該是安全的。
一旦<One />
實例被卸載,ref 上的current
屬性將返回為null
。
一般來說,如果你需要傳遞一個在調用時可能沒有設置的引用,你可以傳遞一個 lambda:
<One ref={c => this.one = c}/>
<Two one={() => this.one}/>
然后將其引用為
this.props.one()
如果在您調用它時已設置它,您將獲得一個值。 在此之前,您會得到undefined
(假設它沒有被初始化)。
值得注意的是,當它可用時,您不一定會重新渲染,我希望它在第一次渲染時undefined
。 這是使用 state 來保存您的參考確實可以處理的事情,但您不會獲得多次重新渲染。
鑒於這一切,我會建議任何代碼用的是裁判移動One
在Two
成被渲染組件One
和Two
,避免一切與這兩個戰略,一個在@Carl斯維爾的答案的問題。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.