【问题标题】:What is the best way to update an object in a usestate and see the change immediately更新使用状态中的对象并立即查看更改的最佳方法是什么
【发布时间】:2021-10-09 13:27:54
【问题描述】:
const TestScreen = (props) => {

    const [data, setData] = useState([ 
            { "id": "0", "user": "Lisa","amount": 1 },
        ]);

        return(
            <View style={{
                            flex:1, 
                            alignItems:'center',
                            justifyContent:'center'
                        }}>
            <Text>amount : {data[0].amount}</Text>
            <Text>User : {data[0].user}</Text>
            <Button title="update" onPress={()=>setData(??????)}></Button>
          </View>
           
        )
    }
  
  export default TestScreen;

在用户 Lisa 上添加金额数字的最佳方法是什么?我可以 // setData([{ "id": "0", "user": "Lisa","amount": data[0].amount + 1}]) 但是我有 5 个用户还是 20 个用户?

即使有返回函数,除了控制台记录的女巫显示实际值外,没有任何更新

   let countAddFunc =(getArr)=>{
          let arr = getArr
          arr[0].amount++
          console.log(arr[0].amount);
          return(
            arr
          )
        }

<Button title="update" onPress={()=>setData(countAddFunc(data))}></Button>

【问题讨论】:

    标签: reactjs react-native react-hooks jsx use-state


    【解决方案1】:

    您可以尝试一次,将第二个参数作为您要更新的用户 ID 传递

    &lt;Button title="update" onPress={()=&gt;setData(countAddFunc(data, 0))}&gt;&lt;/Button&gt;

    let countAddFunc =(getArr, id)=>{
              const arrCopy = [...getArr]
              const user = arrCopy.find(u => u.id === id )
              if (user) {
                 user.amount++
              }
              return arrCopy
            }

    其实你是直接修改状态,我们不能直接更新状态,getArr只是对状态中数据的引用,所以,我们创建了一个数组的副本,修改了复制的数组,然后我们设置这个新的数组进入状态,关于抛出未定义错误的代码,添加检查,如果(用户)user.amount++ 并确保您发送的 id onPress={()=>setData(countAddFunc(data, 0))} 确实存在

    【讨论】:

    • 我试过你的代码,我得到了undefined is not an object(evaluating 'user.amount')
    • 当将 [...getArr] 添加到 countAddFunc() 中时,工作就完成了...这是为什么呢?
    • 其实你是直接修改state,不能直接更新state,getArr只是对state中数据的引用,所以,我们创建了一个array的copy,修改了copy的array,然后我们将这个新数组设置为状态,关于抛出未定义错误的代码,添加检查,如果(用户)user.amount++ 并确保您发送的 id onPress={()=>setData(countAddFunc(data, 0)) } 实际存在
    【解决方案2】:

    将 setState() 视为更新组件的请求而不是立即命令。为了更好地感知性能,React 可能会延迟它,然后一次更新多个组件。 React 不保证立即应用状态更改。 setState() 并不总是立即更新组件。它可能会批量更新或将更新推迟到以后。这使得在调用 setState() 之后立即读取 this.state 是一个潜在的陷阱。

    阅读官方文档了解更多信息here

    另外,如果您希望回调立即触发并进行更改,您可以使用 useRef 或 useEffect 与依赖数组。

    【讨论】:

    • 我尝试添加 useEffect 它不会注销任何东西useEffect(() =&gt; { console.log("Logged out"); },[data]);
    • 但是当添加 [...getArr] 时,任务完成并在 useEffect "Logged out" 中打印出来,这是为什么呢?如果添加 [...getArr] 然后只是 getArr let countAddFunc =(getArr)=&gt;{ let arr = [...getArr] arr[0].amount++ setData(arr) }
    【解决方案3】:

    React 中的一个关键概念是Do Not Modify State Directly。有时这可能很棘手,尤其是在处理示例中的嵌套数据时(number 作为数组内对象的属性)。

    下面,我重构了你的代码并添加了 cmets 来帮助解释。通过创建一个更新状态的函数,并将该函数传递给每个子组件的 props,子组件将能够通过调用该函数来更新状态。

    const {useState} = React;
    
    // component dedicated to displaying each item in the array
    const Item = (props) => (
      <div style={{
        flex: 1,
        alignItems: 'center',
        justifyContent: 'center',
      }}>
        <div>Amount: {props.item.amount}</div>
        <div>User: {props.item.user}</div>
        <button onClick={() => {
          props.updateAmount(props.item.user);
        }}>Increment</button>
      </div>
    );
    
    const ItemList = () => {
      const [data, setData] = useState([
        {
          id: '0',
          user: 'Lisa',
          amount: 1,
        },
        {
          id: '1',
          user: 'Walter',
          amount: 3,
        },
      ]);
    
      const updateAmount = (user, changeAmount = 1) => {
        // find the index of the item we want
        const index = data.findIndex(item => item.user === user);
    
        // return early (do nothing) if it doesn't exist
        if (index === -1) return;
    
        const item = data[index];
    
        // don't modify state directly (item is still the same object in the state array)
        const updatedItem = {
          ...item,
          amount: item.amount + changeAmount,
        };
    
        // again, don't modify state directly: create new array
        const updatedArray = [...data];
    
        // insert updated item at the appropriate index
        updatedArray[index] = updatedItem;
    
        setData(updatedArray);
      };
    
      return (
        <ul>
          {data.map(item => (
            <li key={item.id}>
              <Item item={item} updateAmount={updateAmount} />
            </li>
          ))}
        </ul>
      );
    };
    
    ReactDOM.render(<ItemList />, document.getElementById('root'));
    <script src="https://unpkg.com/react@17.0.2/umd/react.development.js"></script>
    <script src="https://unpkg.com/react-dom@17.0.2/umd/react-dom.development.js"></script>
    
    <div id="root"></div>

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-04-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-05-01
      • 1970-01-01
      相关资源
      最近更新 更多