function SchrödingersDiff()
{
  const [count, setCount] = useState(0);
  // simulate a changing state
  useEffect(() =>
  {
    const int = window.setInterval(() => setCount(s => s + 1), 1000);
    return () => window.clearInterval(int);
  }, []);

  const last = useRef(0);
  const diff = useMemo(() =>
  {
    const lastValue = last.current;
    last.current = count;
    const diff = count - lastValue;
    // console.log(diff);
    return diff;
  }, [count]);

  // console.log(diff);
  return diff;
}

为什么该组件在<React.StrictMode>以下运行时总是呈现"0"?它在没有严格模式的情况下工作良好(即渲染"1").

我知道strict模式会呈现两次,这可以解释它,但我希望useMemo会捕捉到这一点——事实确实如此:memo函数中的log每秒打印正确的"1".就连外面的那个也有.

有没有更好的方法来计算这个差异?


这是我实际的useState/useEffect/setInterval,已经调整为保留最后一个:

export function useChannel(channelName, initialData, currentOnly)
{
  const socket = useSc(s => s.socket); // gets a SocketCluster socket
  const [data, setData] = useState(currentOnly ? initialData : {current: initialData});

  useEffect(() =>
  {
    if (!socket) return;

    const channel = socket.subscribe(channelName);
    (async () =>
    {
      for await (const data of channel) setData(currentOnly ? data : s => ({current: data, last: s.current}));
    })();

    return () => channel.unsubscribe();
  }, [socket, channelName]);

  return data;
}

推荐答案

您可以定义一个useDiff自定义钩子,该钩子在内部保持当前值和最后值的状态,这样您就可以从setInterval回调中更新这两个值,如下所示:

const useDiff = () => {
  const [state, setState] = useState({
    current: 0,
    last: 0,
  });

  useEffect(() => {
    const interval = window.setInterval(() => {
      setState((s) => ({ current: s.current + 1, last: s.current }));
    }, 1000);
    return () => window.clearInterval(interval);
  }, []);

  return state.current - state.last;
};

演示:https://stackblitz.com/edit/react-akituv

Javascript相关问答推荐

TestCafe预计文本等于以下内容之一

错误:(0,react__WEBPACK_IMPORTED_MODULE_1__.useSYS State)不是函数或其返回值不可迭代

追踪执行顺序

react 页面更改类别时如何返回第0页

即使设置了父级的最大高度,固定位置的分区内容也不会滚动?

Angular 拦截器错误处理删除方法问题

单击按钮后未清除 Select

传递一个大对象以在Express布局中呈现

togglePopover()不打开但不关闭原生HTML popover'

微软Edge编辑和重新发送未显示""

html + java script!需要帮助来了解为什么我得到(无效的用户名或密码)

Websocket错误—有一个或多个保留位开启:reserved1 = 1,reserved2 = 0,reserved3 = 0

使用getBorbingClientRect()更改绝对元素位置

为什么我的自定义元素没有被垃圾回收?

Reaction Redux&Quot;在派单错误中检测到状态Mutations

警告框不显示包含HTML输入字段的总和

我想使用GAS和HTML将从Electron 表格中获得的信息插入到文本字段的初始值中

在查看网页时,如何使HTML中的按钮工作方式类似于鼠标上的滚轮或箭头键?

如何通过Axios在GraphQL查询中发送数组

如何在Java脚本中并行运行for或任意循环的每次迭代