【发布时间】:2021-08-13 19:35:08
【问题描述】:
我有一个 select 函数,它使用 useCallback 使用单个依赖项进行初始化:name。然后我将此函数传递给一些嵌套组件,以便在图表元素上的click 上调用。如果我按照我的方式传递函数(参见下面的示例),结果证明 useCallback 的依赖关系 name 永远不会被识别(如果我通过输入新值来更新输入字段,console.log 会输出旧的 @ 987654328@ 当我点击图表元素时)。任何想法为什么 React 可能会有这种行为?这与类实例化和使用有关吗?问题是我尝试在没有ChartWrapper 和Chart 的裸svg(没有d3)类实例化的情况下使用相同的逻辑 - 它工作正常。所以,问题出在ChartWrapper 或Chart 的更新版本中,使用类而不是组件函数。欢迎任何想法。这是不起作用的最小应用程序的完整代码:
App.js:
import React, {useState, useCallback} from 'react';
import './App.css';
import ChartWrapper from './ChartWrapper';
function App() {
const [name, setName] = useState("some_name")
const nameChangeHandler = (event) => {
setName(event.target.value)
console.log("Updated name to " + event.target.value)
}
const select = useCallback((node) => {
console.log("selected " + node + " for name " + name)
}, [name])
return (
<div className="App">
<ChartWrapper onSelect={select} /><br />
Name: <input name="name" value={name} onChange={nameChangeHandler}/>
</div>
);
}
export default App;
ChartWrapper.js:
import React, { useRef, useState, useEffect } from 'react';
import Chart from './Chart';
const ChartWrapper = (props) => {
const chartArea = useRef(null)
const [chart, setChart] = useState(null)
useEffect(() => {
if (!chart) {
setChart(new Chart(chartArea.current, props.onSelect))
}
else {
chart.update(props.onSelect)
}
}, [chart, props.onSelect])
return (
<div className="chart-area" ref={chartArea}></div>
)
}
export default ChartWrapper
Chart.js:
import * as d3 from 'd3';
import React from "react";
class Chart {
constructor(element, onSelect) {
let vis = this
vis.nodes = [2, 4, 6]
vis.circleSize = 30;
vis.distanceBetweenCircles = 5;
vis.svg = d3.select(element).append('svg')
.attr('width', vis.nodes.length * (vis.circleSize + vis.distanceBetweenCircles))
.attr('height', vis.circleSize)
vis.update(onSelect)
}
update(onSelect) {
let vis = this;
const circlesEnter = vis.svg.selectAll('circle').data(vis.nodes).enter()
circlesEnter.append('circle')
.attr('fill', "gainsboro")
.attr('stroke', "grey")
.style('cursor', 'pointer')
.attr('cx', (d, i) => vis.circleSize/2 + vis.distanceBetweenCircles*i + vis.circleSize*i)
.attr('cy', vis.circleSize/2)
.attr('r', vis.circleSize/2)
.on('click', (event, d) => onSelect(d))
const textsEnter = vis.svg.selectAll('text').data(vis.nodes).enter()
textsEnter.append('text')
.attr('text-anchor', "middle")
.attr('dominant-baseline', "middle")
.attr('font-size', "12")
.style('cursor', 'pointer')
.attr('x', (d, i) => vis.circleSize/2 + vis.distanceBetweenCircles*i + vis.circleSize*i)
.attr('y', vis.circleSize/2)
.text(d => d)
}
}
export default Chart;
【问题讨论】:
标签: javascript reactjs d3.js