useState 对象未正确更新

时间:2021-05-25 10:36:50

标签: reactjs react-hooks use-state

当我们尝试同时更新 useState 对象属性时。它没有更新。

const [stateData, setStatedata] = useState({
id: 0,
name: '',
address: '',
street: '',
city: '',
country: '',
property1: '',
property2: ''
etc...
});

当我尝试在文本更改事件上更新 property1 时

const test = () => {
if(case == 1){
setStatedata({
 ...stateData,
 property1: '123'
});
}
else{
// Do something
}
setStatedata({
 ...stateData,
 property2: '654'
});
}

在这种情况下,property1 的值不会设置为 123。

但它不会等待 property1 值更新。先前更新的值并不总是存在。

如果我需要 20 个或更多状态属性,哪个更好的解决方案?

  1. 对象
  2. 每个属性都有一个状态

3 个答案:

答案 0 :(得分:0)

我试试这个代码对我有用,你可以试试这个: codesandbox

 const [stateData, setStatedata] = useState({
    id: 0,
    name: '',
    address: '',
    street: '',
    city: '',
    country: '',
    property1: '',
    property2: ''
    });
    
   const test = () => {
    setStatedata({
      ...stateData,
      property1: '123'
     });
  
   }
   const test2 = () => {
   
     setStatedata({
      ...stateData,
      property2: '65554'
     });
   }
   console.log(stateData)
  return (
    <div className="App">
      <h1 onClick={() => test()}>Click Here</h1>
      <hr />
      <h1 onClick={() => test2()}>Click Here2</h1>
      <h2></h2>
    </div>
  );

答案 1 :(得分:0)

您应该传递两个参数文本更改事件单击。

  1. 要在状态对象中更改的对象属性名称。例如:- property1
  2. 您要为该对象属性设置的值。例如:- 任何值(文本事件值)

你的测试功能是这样的

const test = (key,value) => {
    setStatedata({...stateData,[key]:value})
}

现在您无需创建多个函数来更改对象值。

答案 2 :(得分:0)

您应该通过以下方式更新状态值:

setStatedata(state=> ({
   ...state,
   property2: '65554'
}));

此外,您可以使用我的库中实现深度状态管理器 (Live Demo) 的自定义钩子:

import React from "react";
import { useAsyncDeepState } from "use-async-effect2";

function TestComponent(props) {
  const [state, setState] = useAsyncDeepState({
    x: 123,
    y: 456
  });

  const incX = () => {
    setState(({ x }) => ({ x: x + 1 }));
  };

  const incY = () => {
    setState(({ y }) => ({ y: y + 1 }));
  };

  return (
    <div className="component">
      <div className="caption">useAsyncDeepState demo</div>
      <div>state.x : {state.x}</div>
      <div>state.y : {state.y}</div>
      <button onClick={() => incX()}>Inc X</button>
      <button onClick={() => incY()}>Inc Y</button>
    </div>
  );
}

如果在异步代码的上下文中使用并且您需要等待更新Live Demo

import React, { useCallback, useEffect } from "react";
import { useAsyncDeepState } from "use-async-effect2";

const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));

function TestComponent(props) {
  const [state, setState] = useAsyncDeepState({
    counter: 0,
    computedCounter: 0
  });

  useEffect(() => {
    setState(({ counter }) => ({
      computedCounter: counter * 2
    }));
  }, [state.counter]);

  const inc = useCallback(() => {
    (async () => {
      await delay(1000);
      await setState(({ counter }) => ({ counter: counter + 1 }));
      console.log("computedCounter=", state.computedCounter);
    })();
  });

  return (<button onClick={inc}>Inc</button>);
}