简体   繁体   English

无法对未安装的组件执行 React state 更新。 使用效果 React-Native

[英]Can't perform a React state update on an unmounted component. useEffect React-Native

I'm developing a chat app using react-native, node, mongoose, socket.io, the problem is, when using socket.io, when I send message from user1 to user2, I'm able to receive the sent message from user1 but the useEffect doesn't re-renders the component to add the new message into the array of messages even though I have entered the correct dependencies. I'm developing a chat app using react-native, node, mongoose, socket.io, the problem is, when using socket.io, when I send message from user1 to user2, I'm able to receive the sent message from user1 but the useEffect doesn't即使我输入了正确的依赖项,也会重新渲染组件以将新消息添加到messages数组中。 Below is the code for reference:以下是供参考的代码:

This is my MessageScreen & I have defined socket outside the scope of functional component MessageScreen :这是我的 MessageScreen 并且我在功能组件MessageScreen的 scope 之外定义了socket

const socket = io('ws://192.168.29.123:8080', {
    transports: ['websocket'],
}); // declared outside the functional component

const [arrivalMessage, setArrivalMessage] = useState(null);

    useEffect(() => {
        socket.on('getMessage', data => {
            console.log('received: ',data);
            setArrivalMessage({
                matchId: matchId,
                senderId: data.senderId,
                text: data.text,
                createdAt: Date.now(),
                updatedAt: Date.now(),
            });
        });
        console.log('arrival msg: ',arrivalMessage);
    // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [arrivalMessage, socket]);

    useEffect(() => {
        // ensures we don't get anyother user's msg
        arrivalMessage &&
        match.includes(arrivalMessage.senderId) &&
        setMessages((prev) => [...prev, arrivalMessage]);
    }, [arrivalMessage, match]);

    useEffect(() => {
        socket.emit('addUser', uid);
    }, [uid]);

Although I'm receiving the correct data from my friend but the state is not updating & therefore I'm not able to display real-time messages.虽然我从朋友那里收到了正确的数据,但 state 没有更新,因此我无法显示实时消息。 So, whenever I send a message from 1 user to another, this is my console output which confirms that I am able to receive the message from that user & obviously the title error:因此,每当我从一个用户向另一个用户发送消息时,这就是我的控制台 output ,它确认我能够从该用户接收消息并且显然是标题错误:

LOG  received:  {"senderId": "61b5d1725a7ae2994", "text": {"matchId":"61b5d172511867ae298c", "senderId": "61b5d1725a7ae2994", "text": "me too!"}}
ERROR  Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function. in MessageScreen (at SceneView.tsx:126)
LOG  received:  {"senderId": "61b5d1725a7ae2994", "text":{"matchId":"61b5d111867ae298c","senderId":"61b5d1725a7ae2994", "text": "me too!"}}

It would be really helpful if someone could point out what is wrong here!如果有人能指出这里有什么问题,那将非常有帮助! Thank you!谢谢!

You need to turn off the socket listener when the component unmounts组件卸载时需要关闭套接字侦听器

 useEffect(() => {
        const callback = data => {
            console.log('received: ',data);
            setArrivalMessage({
                matchId: matchId,
                senderId: data.senderId,
                text: data.text,
                createdAt: Date.now(),
                updatedAt: Date.now(),
            })
        }
    
        socket.on('getMessage', callback);
        console.log('arrival msg: ',arrivalMessage);

        // ADD THIS
        return () => {
          socket.off(event, callback)
        }
    
    // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [arrivalMessage, socket]);

You also don't want the socket to run if not necessary.如果没有必要,您也不希望套接字运行。 I would not initiate the socket out of the component, it may stay in the memory and cause memory leaks.我不会从组件中启动套接字,它可能会留在 memory 中并导致 memory 泄漏。

Better approach is to make a context where you initiate your socket and wrap your app/components that needs it.更好的方法是创建一个上下文,您可以在其中启动套接字并包装需要它的应用程序/组件。 If your component unmounts, socket disconnects.如果您的组件卸载,套接字将断开连接。

import SocketClient from 'socket.io-client'

export function useSocket(url) {
  const [socket, setSocket] = useState(null)

  useEffect(() => {
    const io = SocketClient(url).connect()
    setSocket(io)

    return () => {
      socket?.disconnect()
    }

    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [])

  return socket
}

const SocketsContext = createContext({
  socket: undefined,
})

function SocketsContextProvider({ children }) {
  const socket = useSocket()

  return (
    <SocketsContext.Provider value={{ socket }}>
      {children}
    </SocketsContext.Provider>
  )
}

export function useSocketEvent(event, callback) {
  const { socket } = useContext(SocketsContext)

  useEffect(() => {
    if (!socket) {
      return
    }

    socket.on(event, callback)

    return () => {
      socket.off(event, callback)
    }
  }, [callback, event, socket])

  return socket
}

function ParentComponentWithSockets(){
  return (
    <SocketsContextProvider>
      <YourComponent />
    </SocketsContextProvider>
  )
}

function YourComponent(){
  const [arrivalMessage, setArrivalMessage] = useState(null);

  useSocketEvent('getMessage', data => {
    setArrivalMessage({
       matchId: matchId,
       senderId: data.senderId,
       text: data.text,
       createdAt: Date.now(),
       updatedAt: Date.now(),
    })
  })

  return (
   //...
  )
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 警告:无法对未安装的组件执行 React state 更新。 使用效果清理 function - Warning: Can't perform a React state update on an unmounted component. useEffect cleanup function 如何修复“无法在未安装的组件上执行React状态更新。” React Native中的错误 - How to fix “Can't perform a React state update on an unmounted component.” error in React Native 无法使用 useEffect 挂钩对未安装的组件执行 React state 更新 - Can't perform a React state update on an unmounted component with useEffect hook 无法使用 useEffect 对未安装的组件问题执行反应状态更新 - can't perform a react state update on an unmounted component issue with useEffect React-Native:警告:无法对卸载的组件执行 React 状态更新 - React-Native: Warning: Can't perform a React state update on an unmounted component React Native:无法对未安装的组件执行 React state 更新 - React Native: Can't perform a React state update on an unmounted component React 警告:无法对卸载的组件执行 React 状态更新。 要修复,请取消所有订阅 - React Warning: Can't perform a React state update on an unmounted component. To fix, cancel all subscriptions React:ComponentDidMount 中的 SetInterval 导致错误“警告:无法在未安装的组件上执行 React 状态更新。” - React: SetInterval in ComponentDidMount causing error "Warning: Can't perform a React state update on an unmounted component." 无法对卸载的组件执行 React 状态更新。 (类组件) - Can't perform a React state update on an unmounted component. (Class component) 无法对未安装的组件执行反应 state 更新。 这是一个空操作,但它表示 memory 泄漏 - can't perform a react state update on an unmounted component. this is a no-op but it indicates a memory leak
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM