react immer,use-immer setXXX 改值存储数据问题

用immer,use-immer在父组件中存值,部分代码如下:
在saveFormData函数中,value有值,
push后,createModelData.tableFormData里没有值.
错在哪里了?

import produce from'immer';
import { useImmer } from"use-immer";
export default () => {
 ... ... 
  const [createModelData, setCreateModelData] = useImmer({
    tableFormData: [],
    connectFormData: [],
    polymerizeFormData: []
  });
  
  //子组件调用父组件函数,传了value值
  const saveFormData = (value) => {
    console.log(value)  //有值
    setCreateModelData(draft => {
      draft.tableFormData.push(value);
    });
    console.log(createModelData.tableFormData) //无值
  }
  ... ...
阅读 6.5k
4 个回答

useImmer 在实现上用了useState

export function useImmer<S = any>(
  initialValue: S | (() => S)
): [S, (f: (draft: Draft<S>) => void | S) => void];
export function useImmer(initialValue: any) {
  const [val, updateValue] = useState(initialValue);
  return [
    val,
    useCallback(updater => {
      updateValue(produce(updater));
    }, [])
  ];
}

这里的更新流程跟直接使用 useState 没区别,而 useState 的更新是异步的(跟 class 的 setState 一致),所以在后面不会直接获取到最新的值。

所以你这里没有任何错误,是你没理解 useState 之类的更新流程。

export default function App() {
  const [data, update] = useState({
    data: []
  });

  const onClick = () => {
    update({
      data: [...data.data, "test"]
    });
    console.log(data.data, "111");
  };

  return (
    <div className="App">
      <h1 onClick={onClick}>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>
      {data.data.map(item => (
        <p>{item}</p>
      ))}
    </div>
  );
}
console.log(createModelData.tableFormData) 

这个在刚刚调用了set的时候确实取不到值
在render里面打印呢 应该是可以获取到的

可以用useState吧

const [createModelData, setCreateModelData] = useState({
    tableFormData: [],
    connectFormData: [],
    polymerizeFormData: []
  });
//子组件调用父组件函数,传了value值
  const saveFormData = (value) => {
    console.log(value)  //有值
    setCreateModelData(draft => {
      return {
        ...draft,
        tableFormData: [...draft.tableFormData, value]
      }
    });
  }
新手上路,请多包涵

最近在研究immer,遇到了和你一样的问题,use-immer更新后无法及时获得相应值,说是异步的问题,但useState是异步,console却是最新值(类似的逻辑)。而且use-immer,我试过延迟3秒打印当前值,也是旧值,而render里面却是可以及时更新的。甚至use-immer利用interval打印当前值,会疯狂循环曾经的值。目前我所想到的在render外的解决方案就是利用useEffect来检测磁值,更新后进行相应其他操作。但是如果非要拿这么才能操作,感觉use-immer的意义真的不大了,完全可以用useState操作啊。不是很明白这到底是什么原因,如果你已经搞清楚了,麻烦也和我交流一下~

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏