最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - React - UseState - How to partially update state object - Stack Overflow

programmeradmin2浏览0评论

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

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

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 ?

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

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

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 ?

Share Improve this question edited Sep 15, 2020 at 16:23 skyboyer 23.8k7 gold badges62 silver badges71 bronze badges asked Sep 14, 2020 at 10:17 lucas24007lucas24007 1532 silver badges10 bronze badges 1
  • setElephantProp is Async method that's why this happening. When you are looping through it you not get the state updated value. so last value get updating. Can you please try the same with for loop it sync and forEach is Async. Hope it will help you. – Gaurang Doshi Commented Sep 14, 2020 at 10:22
Add a ment  | 

5 Answers 5

Reset to default 4

From you code I am going to assume that input is an object representing the state updates, e.g.

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

In this case you can simply do:

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

As ...input e last, its properties will overwrite elephantProp properties that have the same key. Please notice in this way all input keys which are not present in elephantProp, will be added to the state; e.g.

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 plex state logic that involves multiple sub-values - 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 remends using multiple states for the different variables. However, if you did want to set a full object, you'd likely rather copy the object, and setState only once. 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:

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

One of your solutions here: codesandbox.io or bellow code using this approach.

  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>
发布评论

评论列表(0)

  1. 暂无评论