在useEffect中反应功能组件访问状态

React functional component access state in useeffect

我有一些像下面这样的反应组件。我可以在 return 中使用“消息”,但是如果我尝试在某些函数或 useEffect 中访问消息,例如,我总是成为初始值。如何在功能组件中解决它?谢谢

const Messages = () => {

   const { websocket } = useContext(WebsocketsContext);

   let [ messages, setMessages ] = useState([]);

   useEffect(() => {
      getMessages()
      .then(result => {
         setMessages(result);
      })
   }, []);

   useEffect(() => {
      if(websocket != null){
         websocket.onmessage = (msg) => {
            let wsData = JSON.parse(msg.data);

            if(wsData.message_type == 'Refresh'){
               console.log(messages)
            };
         };
      };
   }, [websocket]);

   return(
        <div>...</div>    
   );

};
export default Messages;

看来你遇到了stale closure

只要 websocket reference/value 发生变化,其依赖数组中带有 [websockets] 的 useEffect 只会“更新”。无论何时,该函数都会在那个时间点围绕 messages 创建一个“闭包”。因此,消息的值将在该闭包内保持原样。如果消息在 websocket 创建后更新,它永远不会更新 onmessage 回调函数中的“消息”值。

要解决此问题,请将“消息”添加到依赖项数组。 [websockets, messages]。这将确保 useEffect 回调始终具有最新的消息状态,并且 onmessage 函数将具有最新的消息状态。

 useEffect(() => {
      if(websocket != null){
         websocket.onmessage = (msg) => {
            let wsData = JSON.parse(msg.data);

            if(wsData.message_type == 'Refresh'){
               console.log(messages)
            };
         };
      };
   }, [websocket, messages]);

因为你的getMessages()是一个异步函数。顺序如下:组件最初安装并初始化值 -> componentDidMount() 被调用意味着你的 getMessages() 被调用(一个异步函数!) -> 你的 webaocket 被初始化并调用第二个 useEffect,它读取 messages 的初始值 -> 你的 getMessages 得到它的响应并相应地设置 messages

要使其按预期工作,请将第二个 useEffect 的依赖项数组设为 [websocket, messages]