【问题标题】:React - UseState - How to partially update state objectReact - UseState - 如何部分更新状态对象
【发布时间】:2020-09-14 10:17:27
【问题描述】:

问题

嗨,

我正在尝试部分更新我的状态对象:

const [elephantProp, setElephantProp] = useState({
        name: "",
        color: "",
        size: "",
        race: "",
        country: "",
    });

假设我只想更新颜色和尺寸参数。

我尝试过的

1

动态改变参数(根据输入对象):

const handleChange = (input) => {
    Object.keys(input).forEach((key) => {
        setElephantProp({ ...elephantProp, [key]: input[key] });
    };

输出:仅更改最后一个参数(大小)。

2

一次性设置所有参数:

const handleChange = (input) => {
        setElephantProp({ ...elephantProp, color: input.color, size: input.size });
    };

输出:有效但不是动态的(如果我向输入对象添加参数将没有效果)

你对如何动态更新我的一些状态变量有什么想法吗?

也许我应该考虑拆分成多个状态变量(变量太多不方便)或使用嵌套对象?

【问题讨论】:

  • setElephantProp 是异步方法,这就是发生这种情况的原因。当您遍历它时,您不会获得状态更新值。所以最后一个值得到更新。你能不能试试 for 循环它同步和 forEach 是异步的。希望对您有所帮助。

标签: javascript reactjs react-hooks state


【解决方案1】:

根据您的代码,我将假设 input 是一个表示状态更新的对象,例如

{
    name: "Dumbo",
    country: "USA"
}

在这种情况下,您可以简单地这样做:

const handleChange = (input) => {
    setElephantProp({ ...elephantProp, ...input });
}

由于...input 排在最后,它的属性将覆盖具有相同键的elephantProp 属性。 请注意,所有在elephantProp 中不存在的input 键都将被添加到状态中;例如

const elephantProp = {
  name: "",
  color: "",
  size: "",
  race: "",
  country: "",
};

const input = {
  name: "Dumbo",
  country: "USA",
  ableToFly: true,
};

const updatedElephantProp = {
  ...elephantProp,
  ...input
} // => the updated state will contain the key/value pair 'ableToFly: true' too

console.log(updatedElephantProp)

这种行为可能是可取的,也可能不是,取决于您的需求和项目规范。

【讨论】:

  • 谢谢!它完全符合我的需求,因为我可以控制可以存储在输入对象中的内容。现在我的 handleChange 函数看起来像这样:` const handleChange = (input) => { setElephantProp({ ...elephantProp, ...input }); }; `
【解决方案2】:

React 建议对不同的变量使用多种状态。 但是,如果您确实想设置一个完整的对象,您可能宁愿复制该对象,并且 setState 只复制一次。您的循环可能不会被重新渲染正确捕获,因为它是一个异步函数。

我不确定你的实现是什么,但是这样的东西应该可以工作:

const handleChange = (objectIn) => {
  // create a new object merging the old one and your input
  const newElephant = {
    ...elephantProps,
    ...objectIn
  }
  setElephantProps(newElephant)
}

这应该可以优雅地处理您的案件。如果您使用多个输入,我通常会这样处理:

  const onChange = ({ target: { value, name } }) => setElephant({
    ...elephant,
    [name]: value
  })
  return <input onChange={onChange} name="size" value={elephant.size} />

【讨论】:

    【解决方案3】:

    您可以将第二个参数传递给handleChange,例如:

    const handleChange = (input, name) => {
        setElephantProp({ ...elephantProp, [name]: input[name] });
    };
    

    【讨论】:

      【解决方案4】:

      您的解决方案之一here: codesandbox.io 或使用此方法的以下代码。

        const onChangeHandaller = (e) => {
          setElephantProp({ ...elephantProp, [e.target.name]: e.target.value });
        };
      

      const [elephantProp, setElephantProp] = useState({
          name: "",
          color: "",
          size: "",
          race: "",
          country: ""
        });
      
        const onChangeHandaller = (e) => {
          setElephantProp({ ...elephantProp, [e.target.name]: e.target.value });
        };
      
        return (
          <div className="App">
            Name:{" "}
            <input
              value={elephantProp.name}
              name="name"
              onChange={(e) => onChangeHandaller(e)}
            />{" "}
            <br />
            Color:{" "}
            <input
              value={elephantProp.color}
              name="color"
              onChange={(e) => onChangeHandaller(e)}
            />{" "}
            <br />
            Size:{" "}
            <input
              value={elephantProp.size}
              name="size"
              onChange={(e) => onChangeHandaller(e)}
            />{" "}
            <br />
            Race:{" "}
            <input
              value={elephantProp.race}
              name="race"
              onChange={(e) => onChangeHandaller(e)}
            />{" "}
            <br />
            Country:{" "}
            <input
              value={elephantProp.country}
              name="country"
              onChange={(e) => onChangeHandaller(e)}
            />{" "}
            <br />
          </div>
      

      【讨论】:

        【解决方案5】:

        您可以使用概念 useReducer - 当您有涉及多个子值的复杂状态逻辑时,通常比 useState 更可取 - useReducer

            const [changes, onChange] = useReducer((value, change) => ({...(value || {}), ...change}), {});
        
            //used
            const {name, color, size, race, country} = changes;
            
            const handleChange = change => {
                //example change = {name: 'alex'}
                onChange(change);
            };
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-11-29
          • 1970-01-01
          相关资源
          最近更新 更多