[英]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>
);
}
它肯定會工作沒問題。 但是隨着您不斷添加越來越多的字段,為每個字段設置單獨的error
和text
掛鈎似乎很乏味並且會生成大量代碼。 所以,為了防止這種情況,我試着用不同的方式寫這個
// ...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.