diff --git a/packages/site/common/react-snippet-strict.md b/packages/site/common/react-snippet-strict.md index cc3ee6b3f1b..7dd51d9ec7a 100644 --- a/packages/site/common/react-snippet-strict.md +++ b/packages/site/common/react-snippet-strict.md @@ -1,47 +1,75 @@ ```tsx -import type { GraphOptions } from '@antv/g6'; -import { Graph as G6Graph } from '@antv/g6'; +import { ExtensionCategory, Graph as G6Graph, register } from '@antv/g6'; +import { ReactNode } from '@antv/g6-extension-react'; import { useEffect, useRef } from 'react'; -export interface GraphProps { - options: GraphOptions; - onRender?: (graph: G6Graph) => void; - onDestroy?: () => void; -} +register(ExtensionCategory.NODE, 'react-node', ReactNode); + +const SelectableNode = (props: { selected: boolean; onToggle: () => void }) => { + const { selected, onToggle } = props; + + return ( + + ); +}; -export const Graph = (props: GraphProps) => { - const { options, onRender, onDestroy } = props; - const graphRef = useRef(); +export default function App() { const containerRef = useRef(null); + const graphRef = useRef(null); useEffect(() => { - const graph = new G6Graph({ container: containerRef.current! }); - graphRef.current = graph; + if (!containerRef.current) return; - return () => { + const handleToggle = (id: string, selected: boolean) => { const graph = graphRef.current; - if (graph) { - graph.destroy(); - onDestroy?.(); - graphRef.current = undefined; - } + if (!graph) return; + + graph.updateNodeData([{ id, data: { selected: !selected } }]); + graph.draw(); }; - }, []); - useEffect(() => { - const container = containerRef.current; - const graph = graphRef.current; + const graph = new G6Graph({ + container: containerRef.current, + width: 500, + height: 300, + data: { + nodes: [{ id: 'node-1', style: { x: 250, y: 150 }, data: { selected: false } }], + }, + node: { + type: 'react-node', + style: { + size: [160, 50], + component: (data) => ( + handleToggle(data.id, Boolean(data.data?.selected))} + /> + ), + }, + }, + }); - if (!options || !container || !graph || graph.destroyed) return; + graphRef.current = graph; + graph.render(); - graph.setOptions(options); - graph - .render() - .then(() => onRender?.(graph)) - // eslint-disable-next-line no-console - .catch((error) => console.debug(error)); - }, [options]); + return () => { + graph.destroy(); + graphRef.current = null; + }; + }, []); - return
; -}; + return
; +} ``` diff --git a/packages/site/docs/manual/getting-started/integration/react.en.md b/packages/site/docs/manual/getting-started/integration/react.en.md index b1e88bfc914..2932bf02f1e 100644 --- a/packages/site/docs/manual/getting-started/integration/react.en.md +++ b/packages/site/docs/manual/getting-started/integration/react.en.md @@ -11,6 +11,6 @@ Refer to the example below, you can use G6 in React, and you can also view the [ ## Strict Mode -In strict mode, React will update twice, causing G6 to create and destroy the Graph instance repeatedly. You can refer to the following example to solve this problem: +In strict mode, React intentionally mounts, unmounts, and remounts components in development. Create the Graph instance inside an effect, keep it in a ref, and destroy it in the cleanup callback so the first development-only mount does not leave a stale graph behind. The following complete example also shows how to register and render a React node. diff --git a/packages/site/docs/manual/getting-started/integration/react.zh.md b/packages/site/docs/manual/getting-started/integration/react.zh.md index 97e47da199f..97af194eeba 100644 --- a/packages/site/docs/manual/getting-started/integration/react.zh.md +++ b/packages/site/docs/manual/getting-started/integration/react.zh.md @@ -15,6 +15,6 @@ order: 0 ## 严格模式 -在严格模式下,React 会二次更新导致 G6 重复创建 Graph 实例并销毁,可以参考如下示例解决: +在严格模式下,React 会在开发环境中有意执行挂载、卸载、再挂载。请把 Graph 实例放在 effect 里创建,用 ref 保存,并在清理函数中销毁,这样第一次开发态挂载不会留下旧实例。下面的完整示例同时演示了如何注册和渲染 React 节点。