ReactJS中Bumbeishvili D3-Org-Chart布局与数据更新异常问题
D3-org-chart + React 功能问题排查
问题概述
已在CodeSandbox上复现并简化问题,当前存在以下问题:
1.(已解决)布局切换后节点展开/折叠异常
点击顶部切换布局按钮后,再点击节点展开/折叠按钮,图表会恢复至原始左到右布局,第二次点击才会执行预期的展开/折叠操作。相关代码:
swapButton.js
const SwapButton = forwardRef(({ onSwapLayout }, ref) => { // const [isCycleLayoutOn, setIsCycleLayoutOn] = useState(false); const swapLayout = (event) => { event.preventDefault(); onSwapLayout(event); }; return ( <div> <button className="context-menu-btns" style={{ backgroundColor: "#4caf50", color: "white", borderRadius: "0.5rem", paddingTop: "0.5rem", paddingBottom: "0.5rem", paddingLeft: "1rem", paddingRight: "1rem", }} onClick={(event) => swapLayout(event)} ref={ref} > <FaRetweet size="2rem" /> </button> </div> ); }); export default SwapButton;
orgChart.js
const OrganizationalChart = (props) => { const d3Container = useRef(null); const chartRef = useRef(null); const [layoutIndex, setLayoutIndex] = useState(0); const handleSwapLayout = useCallback((event) => { if (event) { setLayoutIndex((prevIndex) => (prevIndex + 1) % 4); return layoutIndex; } return layoutIndex; }); useLayoutEffect(() => { const handleLayout = () => handleSwapLayout(); const chart = new OrgChart(); if (props.data && d3Container.current) { chart .container(d3Container.current) .data(props.data) .nodeWidth((d) => 300) .nodeHeight((d) => 150) .layout(["left", "top", "right", "bottom"][handleLayout()]) .compactMarginBetween((d) => 80) .onNodeClick((d) => { toggleDetailsCard(d); }) .buttonContent((node, state) => { return ReactDOMServer.renderToStaticMarkup( <CustomExpandButton {...node.node} /> ); }) .nodeContent((d) => { return ReactDOMServer.renderToStaticMarkup( <CustomNodeContent {...d} /> ); }) .render(); chartRef.current = chart; } }, [props, props.data, handleSwapLayout]); return ( <div style={styles.orgChart} ref={d3Container}> <div style={{ display: "flex", justifyContent: "center", alignItems: "center", padding: "0.5rem", }} > <SwapButton onSwapLayout={handleSwapLayout} ref={d3Container} /> </div> ); }; export default OrganizationalChart;
2. 数据集切换异常
点击切换开关后,需要点击3-4次才能更新节点,且更新结果反向;此外点击展开/折叠按钮会恢复至原始布局。相关代码:
dataToggle.js
const DataToggle = ({ onDataChange, isToggleOn }) => { const handleChange = (event) => { event.preventDefault(); onDataChange(event); }; return ( <div> <span className={!isToggleOn ? "label_txt_unchecked" : "label_txt"}>OFF</span> <label className="switch"> <input checked={isToggleOn} type="checkbox" onChange={(event) => handleChange(event)} /> <span className="slider"></span> </label> <span className={isToggleOn ? "label_txt_checked" : "label_txt"}>ON</span> </div> ); }; export default DataToggle;
App.js
const App = () => { const [data, setData] = useState(employees); const [isToggleOn, setIsToggleOn] = useState(false); const handleDataChange = (event) => { event.preventDefault(); setIsToggleOn(!isToggleOn); if (isToggleOn) { setData(revisedEmployees); } else { setData(employees); } }; return ( <React.StrictMode> <> <h1 style={styles.title}>Organization Chart</h1> <div> <DataToggle onDataChange={handleDataChange} isToggleOn={isToggleOn}/> </div> <OrganizationalChart data={data} /> </> </React.StrictMode> ); };// export default App;
问题推测
问题与DOM未正确清理旧内容有关,可能存在重复渲染或状态未正确保存/更新的情况。
已尝试未成功的方法
- 使用d3-org-chart的
.connectionsUpdate()、.linkUpdate()、.nodeContent()、.nodeUpdate()、.updateNodesState()和.update()方法(不确定是否正确使用) - 组合使用d3的
select()、selectAll()、enter()、append()、join()、merge()、exit()和remove()方法 - 使用React的
useState()、useRef()、useCallback()、useEffect()、useLayoutEffect()和forwardRef()钩子
期望目标
除非刷新页面,否则点击按钮时图表不会恢复至原始布局;点击切换数据集按钮能即时正确更新节点;优先使用d3-org-chart方法解决,也接受其他可行方案。
内容的提问来源于stack exchange,提问作者God Industries
相关产品推荐
相关产品推荐

