其他组件更新共享状态后,如何触发HomeScreen组件的useEffect?
问题根源
你当前的useWebSockets自定义Hook存在核心问题:每次在不同组件中调用这个Hook时,都会创建一套独立的useState状态。也就是说,HomeScreen组件和WebSocket组件里的shouldFetchApplications完全是两个互不相干的变量——WebSocket组件调用setShouldFetchApplications(true)时,只会修改它自己内部的状态,HomeScreen组件的状态根本没变化,自然不会触发依赖该状态的useEffect。
解决方案
要实现跨组件的状态同步,你需要把状态放到一个两个组件都能访问的共享容器里,常用的两种方式如下:
方式一:状态提升到共同父组件
如果两个组件的层级不深,直接把状态提到它们的共同父组件中,通过props传递给子组件即可:
1. 改造共同父组件
import { useState } from 'react' import HomeScreen from './HomeScreen' import WebSocketComponent from './WebSocketComponent' const ParentComponent = () => { // 把状态放在父组件中,作为共享状态 const [shouldFetchApplications, setShouldFetchApplications] = useState(false) return ( <> <HomeScreen shouldFetchApplications={shouldFetchApplications} setShouldFetchApplications={setShouldFetchApplications} /> <WebSocketComponent setShouldFetchApplications={setShouldFetchApplications} /> </> ) } export default ParentComponent
2. 修改HomeScreen组件
不再调用原useWebSockets,直接接收父组件传递的props:
type Props = { shouldFetchApplications: boolean setShouldFetchApplications: (value: boolean) => void } const HomeScreen = ({ shouldFetchApplications, setShouldFetchApplications }: Props) => { // ...其他代码 useEffect(() => { console.log(shouldFetchApplications) // 执行你需要的操作 }, [shouldFetchApplications]) // ...其他代码 }
3. 修改WebSocket组件
同样接收父组件传递的props:
type Props = { setShouldFetchApplications: (value: boolean) => void } const WebSocketComponent = ({ setShouldFetchApplications }: Props) => { // ...其他代码 const onTaskUpdate = () => { setShouldFetchApplications(true) }; // ...其他代码 }
方式二:用React Context共享状态
如果组件层级较深,props传递太繁琐,可以用React Context封装共享状态:
1. 创建WebSocketContext
// WebSocketContext.tsx import { createContext, useContext, useState, ReactNode } from 'react' type WebSocketContextType = { shouldFetchApplications: boolean setShouldFetchApplications: (value: boolean) => void } // 创建Context容器 const WebSocketContext = createContext<WebSocketContextType | undefined>(undefined) // 封装Provider组件,提供共享状态 export const WebSocketProvider = ({ children }: { children: ReactNode }) => { const [shouldFetchApplications, setShouldFetchApplications] = useState(false) return ( <WebSocketContext.Provider value={{ shouldFetchApplications, setShouldFetchApplications }}> {children} </WebSocketContext.Provider> ) } // 封装自定义Hook,简化Context调用 export const useWebSocketContext = () => { const context = useContext(WebSocketContext) if (!context) { throw new Error('useWebSocketContext必须在WebSocketProvider内部使用') } return context }
2. 在根组件中包裹Provider
// App.tsx import { WebSocketProvider } from './WebSocketContext' import HomeScreen from './HomeScreen' import WebSocketComponent from './WebSocketComponent' const App = () => { return ( <WebSocketProvider> <HomeScreen /> <WebSocketComponent /> </WebSocketProvider> ) } export default App
3. 修改HomeScreen组件
使用自定义的Context Hook获取共享状态:
import { useWebSocketContext } from './WebSocketContext' const HomeScreen = () => { const { shouldFetchApplications, setShouldFetchApplications } = useWebSocketContext() // ...其他代码 useEffect(() => { console.log(shouldFetchApplications) // 执行你需要的操作 }, [shouldFetchApplications]) // ...其他代码 }
4. 修改WebSocket组件
同样使用Context Hook获取状态修改方法:
import { useWebSocketContext } from './WebSocketContext' const WebSocketComponent = () => { const { setShouldFetchApplications } = useWebSocketContext() // ...其他代码 const onTaskUpdate = () => { setShouldFetchApplications(true) }; // ...其他代码 }
内容的提问来源于stack exchange,提问作者TreyCollier
相关产品推荐
相关产品推荐

