简体   繁体   English

使 state 与快速发生的事件保持同步

[英]Keep state in sync with fast occuring events

I made a custom hooks keep track of a state variable that is based on the amount of socket events received.我制作了一个自定义挂钩来跟踪基于接收到的套接字事件数量的 state 变量。 When I test by sending 10 simultaneous events the result of the state variable total is 6 or 7 or 8 not the expected 10.当我通过发送 10 个同时事件进行测试时,state 变量总数的结果是 6 或 7 或 8,而不是预期的 10。

const useSocketAmountReceivedState = (event: string): number => {
    const [total, setTotal] = useState(0);

    useEffect(() => {
        Socket.on(event, () => {
            console.log(total);
            setTotal(total + 1);
        });

        return (): void => {
            Socket.off(event);
        };
    });

    return total;
}

The logs of run look something like运行日志看起来像

0
1
1
2
3
3
4
4
4
5

Socket in the example above is implementation around websocket.上例中的Socket是围绕 websocket 实现的。

So I can deduct that total is not updated fast enough, but what is the best pattern to handle this sort of behaviour?所以我可以推断出总数的更新速度不够快,但是处理这种行为的最佳模式是什么?

Try putting an empty array as the second argument in the hook.尝试将一个空数组作为钩子中的第二个参数。 You don't want this to register an event each time the component renders.您不希望它在每次组件呈现时都注册一个事件。

const useSocketAmountReceivedState = (event: string): number => {
    const [total, setTotal] = useState(0);

    useEffect(() => {
        Socket.on(event, () => {
            console.log(total);
            setTotal(total + 1);
        });

        return (): void => {
            Socket.off(event);
        };
    }, [total]);

    return total;
}

UPDATE:更新:

I made an update to my initial answer, and added Total into the dependency array of the React Hook.我对最初的答案进行了更新,并将 Total 添加到 React Hook 的依赖数组中。

Note that the second argument, aka dependency array.注意第二个参数,也就是依赖数组。 It is an array that accepts state or prop.它是一个接受 state 或 prop 的数组。 And it instructs React to run this hook each time any of the elements in the dependency array changes.它指示 React 在每次依赖数组中的任何元素发生变化时运行这个钩子。

If you pass an empty array, then the hook will only be run at initial load, after the component mounts.如果您传递一个空数组,则挂钩将仅在组件安装后的初始加载时运行。

In your example, if you pass an empty array, it creates a closure.在您的示例中,如果您传递一个空数组,它将创建一个闭包。 Hence, the total value will always be the initial value.因此,总值将始终是初始值。

So you can pass Total into the dependency array, which will invoke the useEffect() to run only when Total value changes.因此,您可以将Total传递给依赖数组,该数组将调用 useEffect() 以仅在 Total 值更改时运行。 In your example, where there is no dependency array passed to the second argument, the useEffect() will run every single time, which is not what we want.在您的示例中,没有传递给第二个参数的依赖数组, useEffect() 将每次运行,这不是我们想要的。

Socket.on event has to be outside the useEffect function Socket.on 事件必须在 useEffect function 之外

const useSocketAmountReceivedState = (event: string): number => {
    const [total, setTotal] = useState(0);
    Socket.on(event, () => {
        console.log(total);
        setTotal(total + 1);
    });
    useEffect(() => {
        return (): void => {
            Socket.off(event);
        };
    }, []);

    return total;
}

A colleague came with this solution.一位同事提出了这个解决方案。 Using a reference for which as it is a reference is not enclosed.使用未包含引用的引用。

const useSocketAmountReceivedState = (event: string): number => {
    const count = useRef(0);
    const [state, setState] = useState(0);

    useEffect(() => {
        Socket.on(event, () => {
            count.current++;
            setState(count.current);
        });

        return (): void => {
            Socket.off(event);
        };
    }, []);

    return state;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM