首页 > 解决方案 > useState 钩子返回的更新函数不更新值

问题描述

一些非常奇怪的事情正在发生。我有一个状态值,定义如下:

const [heightField, setHeightField] = useState<FormField<string>>(new FormField<string>(""));

我还定义了一个与该状态值相关的 useEffect 钩子,它的定义如下:

useEffect(() => console.log('heightfield changed, hi from the useEffect hook!'), [heightField]);

此 heightField 值在文本字段中引用,如下所示:

      <TextField
    required
    label="Height (cms)"
    margin="normal"
    variant="outlined"
    type="number"
    value={heightField.value}
    onChange={(event) => {
      setHeightField(new FormField<string>(event.target.value))
    }}
    error={heightField.error}
    helperText={heightField.errorMessage}
  />

现在,当我在文本字段中输入文本时,heightField 值会相应更新,并且 useEffect 挂钩也会被触发。

但是,当从另一个函数更新 heightField 值时,它的值不会更新,也不会触发 useEffect 挂钩。坦率地说,我不明白为什么会发生这种行为。功能如下:

const validateHeight = (heightField: FormField<string>) => {

    const heightNumber = parseInt(heightField.value);
    let error = false;
    let errorMessage = "";
    if (!heightNumber) {
      error = true;
      errorMessage = "Wrong number, please verify.";
    }
    else if (heightNumber < 0 || heightNumber > 220) {
      error = true;
      errorMessage = "Please verify the height";
    }
    const nHeightField = new FormField<string>(heightField.value, error, errorMessage);
    setHeightField(nHeightField);
  }

当点击表单的提交按钮时调用此函数,调用时不会触发 useEffect 钩子,也不会相应更新 heightField 值

有什么我想念的吗?为什么在使用新对象调用更新函数时不更新此值?

标签: reactjsreact-hooks

解决方案


从您在问题和评论中告诉我们的内容来看,state对象引用似乎保持不变,即使它的属性发生了变化。尝试通过执行以下操作来创建该对象的副本:

setState({...heightField});

或者,如果您在更新之前需要以前的state内容:

setState((prevState) => {
 const aux = {...prevState};
 aux.someProp = someOtherValue;
 return aux;
});

如果你的 state 是一个对象,并且对象引用在两次渲染之间保持不变,React 会认为它没有改变并且不会更新它。因为它只比较值。如果是 anumber或 a string,它将按值进行比较,但如果是 a object,它将按引用进行比较,并且不会深入object研究属性。


推荐阅读