【问题标题】:React state hooks array element not updating state反应状态挂钩数组元素不更新状态
【发布时间】:2021-10-23 12:00:39
【问题描述】:

我正在尝试通过 rn-material-ui-textfield 模块在表单中减少代码和/或优化 React 状态挂钩的使用。通常,对于单个文本字段,您可以执行以下操作

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() 确实按照我的预期打印出来。它将所有值添加到数组中并打印出完整的数组。但是,元素中的状态并没有改变。我坚信这与 React 处理钩子的方式有关,而不是 &lt;OutlinedTextField /&gt; 中的错误或其他什么。这就是我将其留在这里的原因。

如果这种方法在 React 中是不可能的,请提出另一种方法来有效地编写代码来声明和使用这些文本字段,而无需声明所有这些错误挂钩。

【问题讨论】:

    标签: javascript arrays reactjs react-native react-hooks


    【解决方案1】:

    这是因为 React 认为 Array 没有因为指向同一个引用而改变。数组本身的内容发生了变化,但是 React 只检查是否是同一个 Array,而不是内容。

    有两种不同的解决方案,第一种是创建一个具有相同内容的新数组,例如:

     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 钩子,它可能更符合您要实现的内容

    【讨论】:

    • 不,这不起作用。在这里,console.log() 表示This was set as error: ,,,,,。我会检查 useReducer 钩子,不过谢谢。
    【解决方案2】:

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

    set_error_arr(temp); 时 React 不会触发重新渲染的原因是 JS 数组的工作方式。 temp 持有对数组的引用。这意味着,即使值可能会改变参考也没有。因为,引用没有改变,React 不承认你的数组发生了改变。通过编写[...temp],您正在创建一个新数组(也是对点的新引用),因此 React 确认发生了更改并将触发重新渲染。

    在使用 JS 对象时也会发生这种情况

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-05-19
      • 1970-01-01
      • 1970-01-01
      • 2020-10-28
      • 2020-03-29
      • 1970-01-01
      • 2021-03-22
      • 1970-01-01
      相关资源
      最近更新 更多