[英]Call methods on React children components
我想編寫一個Form組件,可以導出一個方法來驗證其子代。 不幸的是,表格並沒有“看到”其子女的任何方法。
以下是我如何定義Form的潛在子級:
var Input = React.createClass({
validate: function() {
...
},
});
以下是我定義Form類的方法:
var Form = React.createClass({
isValid: function() {
var valid = true;
this.props.children.forEach(function(component) {
// --> This iterates over all children that I pass
if (typeof component.validate === 'function') {
// --> code never reaches this point
component.validate();
valid = valid && component.isValid();
}
});
return valid;
}
});
我注意到我可以使用refs調用子組件上的方法,但我不能通過props.children調用方法。
這個React行為有原因嗎?
我怎樣才能解決這個問題?
技術原因是,當您嘗試訪問子組件時,它們實際上還不存在(在DOM中)。 他們尚未安裝。 它們已作為構造函數prop或方法作為反應類傳遞給<Form>
組件。 (因此React.createClass()
的名稱類)。
正如你所指出的,這可以通過使用refs來規避,但我不推薦它。 在許多情況下,refs往往是反應不適合的東西的捷徑,因此應該避免。
可能是設計反應使得父母很難/不可能獲得孩子的方法。 他們不應該這樣做。 孩子的方法應該在孩子身上,如果他們是孩子的私人方式:他們在孩子內部做一些事情,不應該直接向父母傳達。 如果是這種情況,那么應該在父母內部進行處理。 因為父母至少擁有孩子擁有的所有信息和數據。
現在在你的情況下,我想每個輸入(子)組件都有某種特定的驗證方法,它檢查輸入值,並根據結果,做一些錯誤信息反饋。 讓我們說一個不正確的字段周圍的紅色輪廓。
在反應方式中,這可以通過以下方式實現:
<Form>
組件具有state,其中包含runValidation
boolean。 runValidation
在setState( { runValidation: true });
內設置為true setState( { runValidation: true });
反應會自動重新呈現所有孩子。 runValidation
包含為所有子項的prop。 if (this.props.runValidation) { this.validate() }
類的東西來檢查他們的render()
函數。 validate()
函數 現在還沒有解決的問題是,您可能希望在所有孩子都自己驗證后在表單級別進行一些檢查:例如,當所有孩子都可以時,請提交表單。
要解決這個問題,您可以將refs快捷方式應用於最終檢查並提交。 並在componentDidUpdate()
函數內的<Form>
實現一個方法,以檢查每個孩子是否正常(例如,有綠色邊框)和是否單擊了提交,然后提交。 但作為一般規則,我強烈建議不要使用引用。
對於最終表單驗證,更好的方法是:
<Form>
添加一個非狀態變量,該變量為每個孩子保留布爾值。 注意,它必須是非狀態的,以防止兒童觸發新的渲染周期。 validateForm
函數作為(回調)道具傳遞給每個子項。 this.props.validateForm(someChildID)
validate()
內,調用this.props.validateForm(someChildID)
,它更新Form中變量的相應布爾值。 validateForm
函數的末尾,檢查所有布爾值是否為真,如果是,則提交表單(或更改表單狀態或其他)。 對於一個更長的(並且更復雜的)解決方案來形成反應中的驗證(使用flux),您可以查看本文 。
我不確定我是否遺漏了什么,但是在嘗試@wintvelt建議我在React的render方法中調用runValidation
方法時遇到問題,因為在我的情況下runValidation
通過調用setState
來改變狀態因此觸發渲染方法顯然是一種不好的做法,因為渲染方法必須是純粹的,如果我把runValidation
放在willReceiveProps
,它將不會第一次被調用,因為if
條件不是真的(這個條件在使用setState
的父組件,但在第一次調用willReceiveProps
它仍然是假的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.