React 功能组件访问状态 in useEffect

Posted

技术标签:

【中文标题】React 功能组件访问状态 in useEffect【英文标题】:React functional component access state in useeffect 【发布时间】:2021-04-15 15:00:34 【问题描述】:

我有一些如下所示的反应组件。作为回报,我可以使用“消息”,但如果我尝试访问某个函数或 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;

【问题讨论】:

【参考方案1】:

您好像遇到过stale closure

在其依赖数组中带有 [websockets] 的 useEffect 只会在 websocket 引用/值更改时“更新”。无论何时,该函数都会在那个时间点围绕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]);

【讨论】:

谢谢,这很容易)【参考方案2】:

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

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

【讨论】:

以上是关于React 功能组件访问状态 in useEffect的主要内容,如果未能解决你的问题,请参考以下文章

测量你的组件在 React Native 功能组件中渲染的次数

React:如何使用功能性 usestate/useEffect 复制特定的组件类 setstate 回调示例?

(现代)React 功能组件可以在外部公开有状态方法吗?

React:使用 Refs 修复缺少的依赖警告 useEffect

如何取消firebase的useEffect订阅

如何将状态值从一个组件访问到位于单独文件中的其他功能(不是组件)?反应js