我正在用 socket.io 开发nextJS应用程序。我已经在上下文中初始化了套接字,并在组件之间共享实例。但是对于其中一个组件,尽管套接字实例被重新初始化,但我在页面刷新后得到 null。
socket.context
const SocketInstance = ({ children }) => {
const socketRef = useRef(null);
useEffect(() => {
const socket = io();
socketRef.current = socket;
console.log(socket); // getting socket instance after refresh
},[])
return (
<SocketContext.Provider
value={{
socket: socketRef.current,
}}
>
{children}
</SocketContext.Provider>
)
}
元件
export default function Home({ onlineUsers }) {
const { socket }= useContext(SocketContext)
const [ users, setUsers ] = useState(onlineUsers || 0);
const [ tab, setTab ] = useState('home');
useEffect(() => {
console.log({socket}) //getting null
socket && socket.on('user', (count) => {
setUsers(count)
})
/* return () => {
socket.off('user')
} */
},[])
return (
<Layout>
<div className="container">
<Head>
<title>Movie Fight</title>
<link rel="icon" href="/favicon.ico" />
</Head>
<p className="fixed top-2 right-2">Online : {users}</p>
</div>
</Layout>
)
}
export async function getServerSideProps(){
const res = await fetch('http://localhost:3000/online');
const onlineUsers = await res.json();
return { props: { onlineUsers } }
}
子组件中的useEffect在父组件之前运行,因此套接字是home在可用之前就被使用了。
在这种情况下,与其将套接字存储在 refs 中,不如将它们存储在状态中,并添加套接字的依赖关系以使用
const SocketInstance = ({ children }) => {
const [socket, setSocket] = useState(null);
useEffect(() => {
const socket = io();
setSocket(socket);
},[])
return (
<SocketContext.Provider
value={{
socket,
}}
>
{children}
</SocketContext.Provider>
)
}
export default function Home({ onlineUsers }) {
const { socket }= useContext(SocketContext)
const [ users, setUsers ] = useState(onlineUsers || 0);
const [ tab, setTab ] = useState('home');
useEffect(() => {
socket && socket.on('user', (count) => {
setUsers(count)
})
},[socket])
return (
<Layout>
<div className="container">
<Head>
<title>Movie Fight</title>
<link rel="icon" href="/favicon.ico" />
</Head>
<p className="fixed top-2 right-2">Online : {users}</p>
</div>
</Layout>
)
}