| English | 中文 |
在 react 中使用 echarts,使用函数式组件进行封装, 并提供 hook 供使用者消费。
echart-for-react,为什么还要编写该组件echarts-for-react在组件上提供 setOption 相关的参数进行图表的更新,这让人感到不适、别扭。
echarts 内部的任何变化与 react 实际上是没有关系的,在props中保持使用静态的参数,通过 chart 实例进行图表更新是比较好的实现方式。
该组件的 props 仅用于对图表的初始化,任何图表的更新通过 ref 获取 echarts 的 instance 进行 setOption。通过内置的 useChart,用户无需考虑图表是否已经准备好,直接 setOption 即可,更新时机在 hook 里决定。
简单的使用方式,使用内部提供的useChart,无需考虑任何时机,通过 ref 获取 echarts instance,直接 setOption ,渲染的时机让 hook 来考虑。或者 你提供 一个用于获取 echarts Instance 的 ref、echarts、onChartReady 函数,即可使用。
一个简单的例子。
import { useCallback, useEffect, useMemo, useState } from "react";
import * as echarts from "echarts/core";
import { GridComponent } from "echarts/components";
import { LineChart } from "echarts/charts";
import { CanvasRenderer } from "echarts/renderers";
import EChartsReact, {
useChart,
EChartsReactProps,
} from "echarts-for-react-fc";
echarts.use([GridComponent, LineChart, CanvasRenderer]);
const TestChart = () => {
const { chartRef, setChartOption, handleListenChartReady } = useChart();
useEffect(() => {
setChartOption({
xAxis: {
type: "category",
data: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
},
yAxis: {
type: "value",
},
series: [
{
id: 1,
data: [150, 230, 224, 218, 135, 147, 260],
type: "line",
},
],
});
setTimeout(() => {
setChartOption({
series: [
{
id: 2,
data: [400, 130, 224, 118, 35, 47, 260],
type: "line",
},
],
});
}, 2000);
}, []);
return (
<EChartsReact
style=
ref={chartRef}
echarts={echarts}
onChartReady={handleListenChartReady}
/>
);
};
export default TestChart;
一个完整的例子。
import { useCallback, useEffect, useMemo, useState } from "react";
import * as echarts from "echarts/core";
import { GridComponent } from "echarts/components";
import { LineChart, PieChart } from "echarts/charts";
import { UniversalTransition } from "echarts/features";
import { CanvasRenderer, SVGRenderer } from "echarts/renderers";
import EChartsReact, {
useChart,
EChartsReactProps,
} from "echarts-for-react-fc";
echarts.use([
GridComponent,
LineChart,
PieChart,
CanvasRenderer,
SVGRenderer,
UniversalTransition,
]);
const TestChart = () => {
const { chartRef, setChartOption, handleListenChartReady } = useChart();
const [renderer, setRenderer] = useState<"svg" | "canvas">("canvas");
const [number, setNumber] = useState(100);
const setR = () => {
setRenderer((old) => {
if (old === "canvas") return "svg" as const;
if (old === "svg") return "canvas" as const;
});
};
const handleClickSetPieOption = () => {
setChartOption(
{
series: [
{
name: "Access From",
type: "pie",
radius: "50%",
data: [
{ value: 1048, name: "Search Engine" },
{ value: 735, name: "Direct" },
{ value: 580, name: "Email" },
{ value: 484, name: "Union Ads" },
{ value: 300, name: "Video Ads" },
],
emphasis: {
itemStyle: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: "rgba(0, 0, 0, 0.5)",
},
},
},
],
},
{
notMerge: true,
}
);
};
const handleClickSetLineOption = () => {
setChartOption(
{
xAxis: {
type: "category",
data: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
},
yAxis: {
type: "value",
},
series: [
{
id: 1,
data: [150, 230, 224, 218, 135, 147, 260],
type: "line",
},
],
},
{
notMerge: true,
}
);
};
useEffect(() => {
setChartOption({
xAxis: {
type: "category",
data: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
},
yAxis: {
type: "value",
},
series: [
{
id: 1,
data: [150, 230, 224, 218, 135, 147, 260],
type: "line",
},
],
});
setTimeout(() => {
setChartOption({
series: [
{
id: 2,
data: [400, 130, 224, 118, 35, 47, 260],
type: "line",
},
],
});
}, 2000);
}, []);
const setNumberFn = useCallback(function (e) {
console.log("The first binding", e);
setNumber(e.value);
}, []);
const events = useMemo<EChartsReactProps["onEvents"]>(() => {
return {
click: [
{
query: { seriesId: "1" },
handler: setNumberFn,
},
{
handler: function (e) {
console.log("The second binding", e);
},
},
],
};
}, [setNumberFn]);
return (
<>
<button onClick={handleClickSetPieOption}>set pie chart</button>
<button onClick={handleClickSetLineOption}>set line chart</button>
<button onClick={setR}>{renderer}set renderer type</button>
<> {number}</>
<EChartsReact
style=
ref={chartRef}
initOpts=
autoResize={true}
onEvents={events}
echarts={echarts}
onChartReady={handleListenChartReady}
/>
</>
);
};
export default TestChart;
| 参数名 | 说明 | 类型 | 是否必填 |
|---|---|---|---|
| echarts | echarts | typeof echarts | Y |
| theme | init fn 参数: 主题 | string | object | N |
| initOpts | init fn 参数: 初始化配置 | EChartsInitOpts | N |
| onChartReady | chart 准备事件 | (ready: boolean) => void; | Y |
| onEvents | 注册事件 | Record<string, EChartsEventInfo | EChartsEventInfo[]> | N |
| autoResize | 监听窗口,resize 图表 | boolean | echarts.ResizeOpts | N |
| style | DOM style | CSSProperties | N |
| classname | DOM classname | string | N |
import * as echarts from "echarts/core";导出 echarts,按模块注册并使用。减少包的体积所需。MIT@mmmml-zhao.
本组件参考 echarts-for-react,感谢该组件贡献者。