为什么需要跨组件实时渲染? 在开发 React 应用时,我们经常遇到这样的场景:某个组件的状态变化需要即时反映在其他不相关的组件中。例如:
用户在一个组件中编辑内容,其他组件需要立即看到更新 多个组件需要共享同一份数据 需要避免通过层层组件传递 props(即所谓的 prop drilling) 这种情况下,使用 React Context 来实现跨组件的实时渲染就显得尤为重要。
最小实现示例 以下是实现跨组件实时渲染的最简代码结构:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 interface SharedContextType { data : any ; updateData : (newData : any ) => void ; } const SharedContext = createContext<SharedContextType | undefined >(undefined );export function SharedProvider ({ children }: { children: React.ReactNode } ) { const [data, setData] = useState<any >(null ); const updateData = useCallback ((newData : any ) => { setData (newData); }, []); return ( <SharedContext.Provider value ={{ data , updateData }}> {children} </SharedContext.Provider > ); } export function useShared ( ) { const context = useContext (SharedContext ); if (!context) { throw new Error ('useShared must be used within SharedProvider' ); } return context; }
实际应用分析 让我们以一个实际的 Mermaid 图表生成器项目为例,分析如何运用这个模式:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 interface HistoryItem { id : string ; content : string ; mermaidCode : string ; timestamp : number ; } export function HistoryProvider ({ children }: { children: React.ReactNode } ) { const [selectedHistory, setSelectedHistory] = useState<HistoryItem | null >(null ); const [historyList, setHistoryList] = useState<HistoryItem []>([]); useEffect (() => { if (selectedHistory) { localStorage .setItem ('selectedHistory' , JSON .stringify (selectedHistory)); } }, [selectedHistory]); const addHistory = async (content : string , mermaidCode : string ) => { const historyItem : HistoryItem = { id : Date .now ().toString (), content, mermaidCode, timestamp : Date .now () }; setHistoryList (prev => [historyItem, ...prev]); }; return ( <HistoryContext.Provider value ={{ selectedHistory , setSelectedHistory , addHistory , historyList }} > {children} </HistoryContext.Provider > ); }
在这个实际例子中,我们可以看到几个关键点:
状态定义 :使用 TypeScript 接口明确定义了数据结构,确保类型安全状态持久化 :通过 useEffect
监听状态变化并保存到 localStorage实时更新 :通过 setHistoryList
确保状态更新后所有使用该 Context 的组件都能即时获得更新当组件需要使用这些共享状态时,只需:
1 2 3 4 5 6 7 8 9 10 11 function HistoryViewer ( ) { const { selectedHistory } = useHistory (); return ( <div > {selectedHistory && ( <div > {selectedHistory.content}</div > )} </div > ); }
这种模式的优势在于:
避免了 props 的层层传递 实现了组件间的解耦 确保了状态更新的实时性 提供了类型安全的数据访问 参考资料