簡體   English   中英

React state 鈎子數組元素不更新 state

[英]React state hooks array element not updating state

我正在嘗試減少代碼和/或優化 React state 掛鈎在帶有rn-material-ui-textfield模塊的表單中的使用。 通常,對於單個文本字段,您可以這樣做

import { OutlinedTextField } from 'rn-material-ui-textfield'
// ...and all the other imports

const example = () => {
    let [text, onChangeText] = React.useState('');
    let [error, set_error] = React.useState('');

    const verify = () => {
        if(!text) set_error('Enter a text');
        else console.log('Finished');
    }

    return(
        <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
            <OutlinedTextField
                onChangeText={onChangeText}
                value={text}
                onSubmitEditing={verify}
                error={error}
              />
        </View>
    );
}

它肯定會工作沒問題。 但是隨着您不斷添加越來越多的字段,為每個字段設置單獨的errortext掛鈎似乎很乏味並且會生成大量代碼。 所以,為了防止這種情況,我試着用不同的方式寫這個

// ...all imports from previous snippet

const example = () => {
    let [inputs, set_input_arr] = React.useState(['', '', '', '', '', '']);
    let [error, set_error_arr] = React.useState(['', '', '', '', '', '']);
    const error_names = ['your name', 'an email ID', 'a password', 'your phone number', "your favourite color", 'your nickname'];

    const set_input = (index, text) => {
        let temp = inputs;
        temp[index] = text;
        set_input_arr(temp);
    };

    const set_error = (index, err) => {
        let temp = error;
        temp[index] = err;
        set_error_arr(temp);
        // this logs the array correctly after running the loop each time
        console.log(`This was set as error: ${error}`);
    };

    const verify = () => {
        for (let i = 0; i < inputs.length; i++) {
            if (!inputs[i]) set_error(i, `Please enter ${error_names[i]}`);
        }
    };
 
    return(
        <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
            <OutlinedTextField
                onChangeText={text => set_input(0, text)}
                value={inputs[0]}
                error={error[0]}
             />
             <OutlinedTextField
                onChangeText={text => set_input(1, text)}
                value={inputs[1]}
                error={error[1]}
             />
             <OutlinedTextField
                onChangeText={text => set_input(2, text)}
                value={inputs[2]}
                error={error[2]}
             />
             <OutlinedTextField
                onChangeText={text => set_input(3, text)}
                value={inputs[3]}
                error={error[3]}
             />
             <OutlinedTextField
                onChangeText={text => set_input(4, text)}
                value={inputs[4]}
                error={error[4]}
             />
             <OutlinedTextField
                onChangeText={text => set_input(5, text)}
                value={inputs[5]}
                error={error[5]}
                onSubmitEditing={verify}
             />
             <Button onPress={verify} title='Verify' />
        </View>
    );
}

它不起作用。 需要明確的是, set_error()中的console.log() ) 確實按照我的預期打印了輸出。 它將所有值添加到數組並打印出完整的數組。 但是,元素中的 state 並沒有改變。 我堅信這與 React 處理鈎子的方式有關,而不是<OutlinedTextField />或其他東西中的錯誤。 這就是為什么我要把它留在這里。

如果這種方法對於 React 是不可能的,請建議另一種方法來有效地編寫代碼來聲明和使用這么多文本字段,而無需聲明所有這些錯誤掛鈎。

要修復此更改set_error_arr(temp); set_error_arr([...temp]); .

編寫set_error_arr(temp); 是因為 JS arrays 是如何工作的。 temp持有對數組的引用。 這意味着,即使值可能發生變化,引用也沒有發生變化。 因為,引用沒有改變,React 不承認你的數組發生了變化。 通過編寫[...temp]你正在創建一個新數組(對 point 的新引用)因此 React 承認發生了變化並將觸發重新渲染。

使用 JS 對象時也會發生這種情況

這是因為 React 認為 Array 沒有改變,因為它指向同一個引用。 數組本身的內容發生了變化,但 React 只檢查是否是同一個數組,而不檢查內容。

有兩種不同的解決方案,第一種是創建一個具有相同內容的新數組,例如:

 const set_error = (index, err) => {
        let temp = [...error];
        temp[index] = err;
        set_error_arr(temp);
        // this logs the array correctly after running the loop each time
        console.log(`This was set as error: ${error}`);
    };

或者您可以查看 useReducer 掛鈎,它可能更符合您要實現的目標

暫無
暫無

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

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