在使用效果中反应功能组件访问状态

时间:2021-01-10 13:30:36

标签: reactjs use-effect use-state react-functional-component

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

2 个答案:

答案 0 :(得分:2)

看起来您遇到了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]);

答案 1 :(得分:1)

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

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