无法对未安装的组件执行 React 状态更新。 useEffect React-Native
Posted
技术标签:
【中文标题】无法对未安装的组件执行 React 状态更新。 useEffect React-Native【英文标题】:Can't perform a React state update on an unmounted component. useEffect React-Native 【发布时间】:2022-01-18 02:49:13 【问题描述】:我正在使用 react-native、node、mongoose、socket.io 开发一个聊天应用程序,问题是,当使用 socket.io 时,当我从 user1 向 user2 发送消息时,我能够接收到发送的消息来自 user1 的消息,但 useEffect
不会重新渲染组件以将新消息添加到 messages
的数组中,即使我输入了正确的依赖项。下面是代码供参考:
这是我的 MessageScreen,我在功能组件 MessageScreen
的范围之外定义了 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]);
虽然我从朋友那里收到了正确的数据,但状态没有更新,因此我无法显示实时消息。 因此,每当我从 1 个用户向另一个用户发送消息时,这就是我的控制台输出,它确认我能够从该用户接收消息并且显然是标题错误:
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!"
如果有人能指出这里有什么问题,那将非常有帮助! 谢谢!
【问题讨论】:
【参考方案1】:组件卸载时需要关闭socket监听
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]);
如果没有必要,您也不希望套接字运行。我不会从组件中启动套接字,它可能会留在内存中并导致内存泄漏。
更好的方法是创建一个上下文,您可以在其中启动套接字并包装需要它的应用程序/组件。如果您的组件卸载,套接字将断开连接。
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 (
//...
)
【讨论】:
像魅力一样工作!非常感谢! 很高兴我能帮上忙 :)以上是关于无法对未安装的组件执行 React 状态更新。 useEffect React-Native的主要内容,如果未能解决你的问题,请参考以下文章
警告:无法对未安装的组件(多个组件)执行 React 状态更新
无法使用 fetch POST 方法对未安装的组件执行 React 状态更新