简体   繁体   English

React - UseState - 如何部分更新状态对象

[英]React - UseState - How to partially update state object

Problem问题

Hi,你好,

I'm trying to partially update my state object :我正在尝试部分更新我的状态对象:

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

Let's say I want to update only color and size parameters.假设我只想更新颜色和大小参数。

What I have tried我试过的

1 1

Dynamically change parameters (according to the input object) :动态改变参数(根据输入对象):

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

Output : change only last parameter (size).输出:仅更改最后一个参数(大小)。

2 2

Set all parameters at once :一次设置所有参数:

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

Output : Works but is not dynamic (if I add a parameter to the input object there will be no effects)输出:有效但不是动态的(如果我向输入对象添加参数,则不会有任何影响)

Do you have any ideas on how to dynamically update some of my state variables ?你对如何动态更新我的一些状态变量有什么想法吗?

Maybe I should consider splitting into multiple state variables (not convenient with a lot of variables) or using nested objects ?也许我应该考虑拆分成多个状态变量(很多变量不方便)或使用嵌套对象?

From you code I am going to assume that input is an object representing the state updates, eg根据您的代码,我将假设input是一个表示状态更新的对象,例如

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

In this case you can simply do:在这种情况下,您可以简单地执行以下操作:

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

As ...input come last, its properties will overwrite elephantProp properties that have the same key....input最后出现时,它的属性将覆盖具有相同键的elephantProp属性。 Please notice in this way all input keys which are not present in elephantProp , will be added to the state;请注意,以这种方式,所有在elephantProp中不存在的input键都将被添加到状态中; eg例如

 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)

This behaviour might be desirable or not, depending on your needs and project specifications.根据您的需要和项目规范,这种行为可能是可取的,也可能是不可取的。

You can use concept useReducer - is usually preferable to useState when you have complex state logic that involves multiple sub-values - useReducer您可以使用概念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);
    };

React recommends using multiple states for the different variables. React 建议为不同的变量使用多个状态。 However, if you did want to set a full object, you'd likely rather copy the object, and setState only once.但是,如果您确实想设置一个完整的对象,您可能宁愿复制该对象,并且只复制一次setState You loop might not be caught properly by the rerendering, as it is an async function.您的循环可能不会被重新渲染正确捕获,因为它是一个异步函数。

I'm not sure what your implementation is, but something like this should work:我不确定你的实现是什么,但这样的事情应该有效:

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

This should handle your case gracefully.这应该可以优雅地处理您的情况。 If you're using multiple inputs, I usually handle it that way:如果您使用多个输入,我通常会这样处理:

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

You can pass 2-nd param to handleChange, for example:您可以将第二个参数传递给 handleChange,例如:

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

One of your solutions here: codesandbox.io or bellow code using this approach.您的解决方案之一:codeandbox.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>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM