创建
创建一个 React Context,用来把"图表预览(或相关共享数据/方法)"放到组件树顶层,
任何子组件都能读取或修改
解决了 "prop drilling"(属性钻取)问题,即:避免将 props 通过多层组件传递
代码编写
js
'use client'
import React, { ReactNode, useMemo, useState } from 'react';
import { createContext, useContextSelector, useContext } from 'use-context-selector';
type PreviewData = {
chartId?: string;
zoom?: number;
// ...其他字段
};
type ChartPreviewContextType = {
preview: PreviewData | null;
setPreview: (p: PreviewData | null) => void;
};
const ChartPreviewContext = createContext<ChartPreviewContextType | undefined>(undefined);
export const ChartPreviewProvider = ({ children }: { children: ReactNode }) => {
const [preview, setPreview] = useState<PreviewData | null>(null);
// useMemo 保证 value 引用稳定,避免无谓重渲染
const value = useMemo(() => ({ preview, setPreview }), [preview, setPreview]);
return (
<ChartPreviewContext.Provider value={value}>
{children}
</ChartPreviewContext.Provider>
);
};
// 简单 hook(如果只需要整个对象)
export const useChartPreviewContext = () => {
const ctx = useContext(ChartPreviewContext);
if (!ctx) throw new Error('useChartPreviewContext must be used within ChartPreviewProvider');
return ctx;
};
// 更细粒度的 selector 用法(推荐:减少重渲染)
// 例如在消费组件中,只订阅 preview 字段:
export const usePreviewData = () => {
const preview = useContextSelector(ChartPreviewContext, v => v?.preview ?? null);
return preview;
};
在任意组件中包裹(通常是最顶级的组件,比如Layout 组件)
js
<ChartPreviewProvider>
{children} // 下面的所有组件都可以使用 useChartPreviewContext 来拿到preview 和 setPreview 如果需要其他 请自行添加
</ChartPreviewProvider>
注意事项
Context 是 React 中非常强大的特性,但需要谨慎使用。
在适当的场景下使用 Context 可以大大简化代码结构,提高开发效率。
但过度使用可能会导致组件复用性降低和性能问题。