组件重新呈现状态

时间:2019-06-27 09:24:56

标签: reactjs react-hooks

export const Component = () => {
    const [messages, setMessages] = useState([]);

    const sendMessage = msg => {
        socket.emit('message', msg);

        setMessages([
            ...messages,
            {
                content: msg.content
            }
        ])
    };

    const onMessage = msg => setMessages([
        ...messages,
        {
            content: msg.content
        }
    ]);

    useEffect(() => {
        socket.on('message', onMessage)
    }, []);

    return (
        <button onClick={() => sendMessage({content: 'test'})}/>
    )
};

这是我如何实现发送/获取消息的示例代码。问题是,如果我从套接字(onMessage)获取消息,则总是重新渲染消息。一切都很好,如果我通过sendMessage函数执行此操作,则消息会充满。

谢谢!

编辑: 我已经解决了这个问题,有答案:

 useEffect(() => {
        socket.on('message', onMessage)
    }, [messages]); //rerender if messages changed

但是我不明白为什么这可以解决我的问题。有人可以解释吗?

编辑2:

 useEffect(() => {
        socket.on('message', onMessage)
        return () => {
          socket.off('message', onMessage);
        }

    }, [messages]); //rerender if messages changed

您如何看待该解决方案?

1 个答案:

答案 0 :(得分:0)

您的问题是一个简单的closure案例,当您在初始加载期间将事件侦听器方法设置为套接字时,onMessage甚至与其词法范围都在使用。但是,在下一个后续渲染期间,将创建一个新的onMessage及其更新的词法作用域,该词法作用域不会重新分配给socket event,因此它将引用其中的messages值,该值在初始加载期间就存在。 >

但是,如果您编写要在每次消息更改时执行的效果,则会将针对消息更改重新呈现而创建的新onMessage方法分配给套接字事件,并且该方法可以正常工作。

但是,比在状态messages中使用useEffect作为依赖项更好的解决方案是使用状态更新回调

const onMessage = msg => setMessages(prevMessages => ([
    ...prevMessages,
    {
        content: msg.content
    }
]));

useEffect(() => {
    socket.on('message', onMessage)
    return () => {
      socket.off('message', onMessage);
    }
}, []);