UNPKG

@antv/s2-react

Version:
145 lines 6.8 kB
import { __awaiter } from "tslib"; import { PivotSheet, TableSheet } from '@antv/s2'; import { PivotChartSheet } from '@antv/s2/extends'; import { useUpdate, useUpdateEffect } from 'ahooks'; import { identity, isEqual } from 'lodash'; import React from 'react'; import { getSheetComponentOptions } from '../utils'; import { useEvents } from './useEvents'; import { useLoading } from './useLoading'; import { usePagination } from './usePagination'; import { useResize } from './useResize'; export function useSpreadSheet(props) { const forceUpdate = useUpdate(); const s2Ref = React.useRef(null); const containerRef = React.useRef(null); const wrapperRef = React.useRef(null); const shouldInit = React.useRef(true); const isDevMode = React.useMemo(() => { try { return process.env['NODE_ENV'] !== 'production'; } catch (_a) { return false; } }, []); const { spreadsheet: customSpreadSheet, dataCfg, options, themeCfg, sheetType, onUpdate = identity, onUpdateAfterRender, onLoading, } = props; /** 保存重渲 effect 的 deps */ const updatePrevDepsRef = React.useRef([dataCfg, options, themeCfg]); const { loading, setLoading } = useLoading(s2Ref.current, props.loading); const pagination = usePagination(s2Ref.current, props.options); useEvents(props, s2Ref.current); const renderSpreadSheet = React.useCallback((container) => { const s2Options = getSheetComponentOptions(options); if (customSpreadSheet) { return customSpreadSheet(container, dataCfg, s2Options); } if (sheetType === 'table') { return new TableSheet(container, dataCfg, s2Options); } if (sheetType === 'pivotChart') { return new PivotChartSheet(container, dataCfg, s2Options); } return new PivotSheet(container, dataCfg, s2Options); }, [sheetType, options, dataCfg, customSpreadSheet]); const buildSpreadSheet = React.useCallback(() => __awaiter(this, void 0, void 0, function* () { var _a; setLoading(true); const s2 = renderSpreadSheet(containerRef.current); s2.setThemeCfg(props.themeCfg); yield s2.render(); setLoading(false); s2Ref.current = s2; /** * 子 hooks 内使用了 s2Ref.current 作为 deps * forceUpdate 一下保证子 hooks 能 rerender */ forceUpdate(); (_a = props.onMounted) === null || _a === void 0 ? void 0 : _a.call(props, s2Ref.current); }), [props, renderSpreadSheet, setLoading, forceUpdate]); // 适用于监听 loading 状态, 组件外部使用 <Spin /> 等场景 React.useEffect(() => { onLoading === null || onLoading === void 0 ? void 0 : onLoading(loading); }, [loading]); React.useEffect(() => { // 兼容 React 18 StrictMode 开发环境下渲染两次 if (isDevMode && !shouldInit.current) { return; } buildSpreadSheet(); shouldInit.current = false; return () => { var _a, _b; setLoading(false); (_b = (_a = s2Ref.current) === null || _a === void 0 ? void 0 : _a.destroy) === null || _b === void 0 ? void 0 : _b.call(_a); }; }, [isDevMode]); // 重渲 effect:dataCfg, options or theme changed useUpdateEffect(() => { const render = () => __awaiter(this, void 0, void 0, function* () { var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m; setLoading(true); const [prevDataCfg, prevOptions, prevThemeCfg] = updatePrevDepsRef.current; updatePrevDepsRef.current = [dataCfg, options, themeCfg]; let rerender = false; let reloadData = false; let rebuildDataSet = false; if (!Object.is(prevDataCfg, dataCfg)) { // 列头变化需要重新计算初始叶子节点 if (((_b = (_a = prevDataCfg === null || prevDataCfg === void 0 ? void 0 : prevDataCfg.fields) === null || _a === void 0 ? void 0 : _a.columns) === null || _b === void 0 ? void 0 : _b.length) !== ((_d = (_c = dataCfg === null || dataCfg === void 0 ? void 0 : dataCfg.fields) === null || _c === void 0 ? void 0 : _c.columns) === null || _d === void 0 ? void 0 : _d.length)) { (_f = (_e = s2Ref.current) === null || _e === void 0 ? void 0 : _e.facet) === null || _f === void 0 ? void 0 : _f.clearInitColLeafNodes(); } reloadData = true; rerender = true; (_g = s2Ref.current) === null || _g === void 0 ? void 0 : _g.setDataCfg(dataCfg); } if (!isEqual(prevOptions, options)) { if ((prevOptions === null || prevOptions === void 0 ? void 0 : prevOptions.hierarchyType) !== (options === null || options === void 0 ? void 0 : options.hierarchyType)) { rebuildDataSet = true; reloadData = true; (_h = s2Ref.current) === null || _h === void 0 ? void 0 : _h.setDataCfg(dataCfg); } rerender = true; (_j = s2Ref.current) === null || _j === void 0 ? void 0 : _j.setOptions(options); (_k = s2Ref.current) === null || _k === void 0 ? void 0 : _k.changeSheetSize(options.width, options.height); } if (!isEqual(prevThemeCfg, themeCfg)) { rerender = true; (_l = s2Ref.current) === null || _l === void 0 ? void 0 : _l.setThemeCfg(themeCfg); } if (!rerender) { setLoading(false); return; } /** * onUpdate 交出控制权 * 由传入方决定最终的 render 模式 */ const defaultRenderOptions = { reloadData, rebuildDataSet, }; const renderOptions = (onUpdate === null || onUpdate === void 0 ? void 0 : onUpdate(defaultRenderOptions)) || defaultRenderOptions; yield ((_m = s2Ref.current) === null || _m === void 0 ? void 0 : _m.render(renderOptions)); setLoading(false); onUpdateAfterRender === null || onUpdateAfterRender === void 0 ? void 0 : onUpdateAfterRender(renderOptions); }); render(); }, [dataCfg, options, themeCfg, onUpdate]); useResize({ s2: s2Ref.current, container: containerRef.current, wrapper: wrapperRef.current, adaptive: props.adaptive, }); return { s2Ref, containerRef, wrapperRef, loading, setLoading, pagination, }; } //# sourceMappingURL=useSpreadSheet.js.map