簡體   English   中英

為什么父組件在設置狀態時不更新輸入組件?

[英]Why parent component does not update input component when setting state?

我有一個像這樣的輸入組件:

let InputBasic = React.createClass({
    displayName: 'InputBasic',
    path: '',
    componentWillMount: function () {
        this.path = this.props.storePath + '.' + this.props.storeIndex;
    },

    getInitialState: function () {
        return { };
    },

    getError: function () {
        if (!Array.isArray(this.props.formErrorFields)) {
            return false;
        };

        __this = this;
        let hasError = false;
        this.props.formErrorFields.forEach(function (index) {
            if (__this.props.name == index.name) {
                hasError = true;
                return;
            }
        });

        return hasError;
    },

    sendToValidation: function() {
        if (this.props.rules) {
            bom.form.validateInput(
            /* Vars here */
            );
        }
    },

    getClassName: function () {

        if(this.getError()) {

            return 'input-basic has-error';
        }
        else {
            return 'input-basic';
        }
    },

    onBlur: function () {
        this.sendToValidation();
    },

    handleChange: function (event) {
        this.setState({ value: event.target.value });
    },

    render: function () {

        return React.createElement('input',
            {
                type: this.props.type,
                placeholder: this.props.placeholder,
                style: this.props.style,
                onChange: this.handleChange,
                onBlur: this.onBlur,
                className: this.getClassName()
            }
        );
    }
});

這個想法是驗證模糊的輸入字段。 如果輸入未通過驗證,則更改包含的表單狀態。 表單setState()函數作為prop傳遞給輸入,然后傳遞給驗證,依此類推。

邏輯適用於設置表單狀態。 相應地設置表單狀態。 我還有另一個組件,它取決於表單狀態,並且完美地工作。 但是,輸入組件未按我的預期更新。

在以下場景中我遇到了問題:

  • 空,初始輸入 - >單擊以觸發onBlur - >驗證失敗 - >輸入組件更新
  • 輸入以輸入 - >單擊以觸發onBlur - >驗證成功 - >輸入組件更新
  • 從輸入中再次刪除文本 - >單擊以觸發onBlur - >驗證失敗 - >輸入組件不更新
  • 再次添加文本到輸入 - >單擊以觸發onBlur - >驗證成功 - >輸入組件確實更新

這是特殊的,因為表格內的其他元素都會更新。 如果我將forceUpdate()添加到onBlur函數,則組件會按預期更新。 然而,這個解決方案感覺很難,特別是因為我不明白為什么我沒有得到預期的效果。

在嘗試解決這個問題時,我想到的是:

  • 這可能是因為組件觸發了最終指向自身的更新過程嗎? 我在這里要問的是,我將setState函數作為道具傳遞出來是一個問題嗎?
  • 在更新方面,輸入組件的處理方式有所不同嗎?

編輯:

這可能是因為onChange函數引起的嗎? 它不在示例中,因為SO嘮叨了太長的代碼示例。

更多編輯:

顯然,如果啟動子項更新,我將如何將值分配給狀態會有所影響。

這是我用來更新輸入父級狀態的函數:

bom.form = {

    getErrorField: function (fields, name, text) {
        let newFields = fields;
        if (fields[name]) {
            newFields[name].hasError = true;
            newFields[name].errorText = text;
        }
        return newFields;

    },

    validateInput: function (inputValue, inputName, inputRules, setFormState, formFields) {
        let fields = formFields;
        if (!inputValue && inputRules.required) {
            let text = 'This field is required.';
            fields = this.getErrorField(formFields, inputName, text);
        }
        state = {};
        state.fields = fields;

        return setFormState(state);
    }
};

所以,調用validateInput()我設置輸入的父組件狀態。

這不會在輸入組件中啟動更新。 但是,如果我將示例中的state.fields賦值更改為:

state.fields = { password: {}, username: {}}

它根據需要啟動更新。 當然,在這個例子中,狀態不是我想要的,這僅僅是為了表達目的。

奇怪的是,在這兩種情況下,另一個不同的子組件(我稱之為fieldMessage)會更新。 它以這種方式呈現:

return React.createElement('p', null, this.getText());

getText()函數返回父組件狀態,它指向右側字段。

所以我已經得出結論,我的問題有關於如何將狀態對象分配給setState()函數。 我對么? 這可能發生,因為我將當前狀態傳遞給子函數,我可能在錯誤的地方使用對象引用,或類似的東西?

您沒有將onBlur處理程序綁定到您的react類。 尤其是:

render: function () {

    return React.createElement('input',
        {
            type: this.props.type,
            placeholder: this.props.placeholder,
            style: this.props.style,
            onChange: this.handleChange,
            onBlur: this.onBlur.bind(this),
            className: this.getClassName()
        }
    );
}

這是因為, this.sendToValidation(); 最終被稱為綁定到事件目標。

我通過分配像這樣的state.fields解決了這個問題:

state.fields = Object.create(fields);

我假設最初的字段指向原始狀態對象引用,因此沒有啟動更新。 然而,這真的只是我的猜測,如果有人能向我澄清這種行為,我將非常感激。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM