【问题标题】:Component rerender state组件重新渲染状态
【发布时间】:2019-11-09 07:01:27
【问题描述】:

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

你觉得这个解决方案怎么样?

【问题讨论】:

  • 你能在渲染消息列表的地方添加sn-p吗?
  • 您的问题对我来说并不完全清楚。你能详细说明一下吗?顺便说一句,每次你的组件更新新消息时都会调用 useState 方法。这将导致向套接字添加多个“onMessage”处理程序。一段时间后,只有 1 条消息会导致如此多的重新渲染。我建议你正确阅读和理解 useEffect hook
  • 你是对的,它每次都会添加监听器,但没有它,它就无法工作。 (消息总是一个空数组)。我已经编辑了我的答案(查看 EDIT 2)。

标签: reactjs react-hooks


【解决方案1】:

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

但是,如果您编写效果以在每次消息更改时执行,则在消息更改重新渲染时创建的新 onMessage 方法将被分配给套接字事件并且它可以正常工作。

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

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

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

【讨论】:

    猜你喜欢
    • 2018-06-05
    • 2023-03-09
    • 2019-10-06
    • 2020-10-24
    • 2019-06-17
    • 2018-04-20
    • 2015-04-26
    • 1970-01-01
    相关资源
    最近更新 更多