我正在使用React Hooks和Redux处理此滑块效果。我的代码如下:
const Barchart = ({chartData}) => {
let newArray = []
let len = chartData.length
const [XArray,setXArray]=useState([chartData])
const [Yarray,setYArray]=useState(chartData[len-1].anArray) //so the initial state here should be an empty array
// const d3Container = useRef(null);
useEffect(()=>{
let len = chartData.length
console.log(chartData.length)
newArray = chartData[len-1].anArray
setYArray(newArray)
if(newArray.length!==0){
const height = 70 //height of the actual chart, different than the svg element
const width = 26.5*newArray.length //width of the actual chart, different than the svg element
const svg = d3.select('.svg-canvas')
svg.selectAll("*").remove()
var x = d3.scaleLinear().domain([0,7]).range([0,width])
var y = d3.scaleLinear().domain([0,d3.max(Yarray)]).range([height,0])
var xAxis = d3.axisBottom(x).ticks(8)
var yAxis = d3.axisLeft(y).ticks(5)
//locate the chart in the middle of the svg frame: 800/2 - width/2
var chartGroup = svg.append('g').attr('transform','translate('+(400 - width/2)+',300)')
chartGroup.selectAll("rect").data(Yarray).enter().append("rect")
.attr("height",(d,i)=>d*3)
.attr("width","15")
.attr("fill","blue")
.attr('x',(d,i)=>26.5*i)
.attr('y',(d,i)=>height-d*3)
chartGroup.selectAll('text').data(Yarray).enter().append("text")
.attr('font-size',15)
.attr('x',(d,i)=>26.5*i)
.attr('y',(d,i)=>height-5-d*3+2)
.text((d,i)=>d)
chartGroup.append('g').attr('class','axis y')
// .attr('transform','translate(500,76)')
.call(yAxis)
chartGroup.append('g').attr('class','axis x')
.attr('transform','translate(0,'+height+')')
.call(xAxis)
}
},[chartData])
const newArrayFunc = (a) =>{
setYArray(a)
}
return(
<div id='chart-container'>
<h3>Bar Chart</h3>
<svg className="svg-canvas" width="800px" height="400px"></svg>
</div>
)
}
const mapStateToProps = state => ({
chartData:state.chartChange
});
export default connect(mapStateToProps)(Barchart)
因此,正如您所见,即使我在useEffect中有setYArray,其异步功能也阻止了Yarray立即被更新。 只要我有一个来自chartData
的新数组,d3条形图就会使用以前的数组。
我要在这里实现的目标是,每当chartData的数组被更新时,更新的数组将立即在d3条形图中使用。
我在这里应该做什么?
答案 0 :(得分:0)
继续使用与更新状态相同的newArray
值
const Barchart = ({ chartData }) => {
let newArray = [];
let len = chartData.length;
const [XArray, setXArray] = useState([chartData]);
const [Yarray, setYArray] = useState(chartData[len - 1].anArray); //so the initial state here should be an empty array
// const d3Container = useRef(null);
useEffect(() => {
let len = chartData.length;
console.log(chartData.length);
newArray = chartData[len - 1].anArray;
setYArray(newArray);
if (newArray.length) { // <-- use in-scope newArray value
const height = 70; //height of the actual chart, different than the svg element
const width = 26.5 * newArray.length; //width of the actual chart, different than the svg element
const svg = d3.select(".svg-canvas");
svg.selectAll("*").remove();
var x = d3.scaleLinear().domain([0, 7]).range([0, width]);
var y = d3
.scaleLinear()
.domain([0, d3.max(newArray)]) // <-- use in-scope newArray value
.range([height, 0]);
var xAxis = d3.axisBottom(x).ticks(8);
var yAxis = d3.axisLeft(y).ticks(5);
//locate the chart in the middle of the svg frame: 800/2 - width/2
var chartGroup = svg
.append("g")
.attr("transform", "translate(" + (400 - width / 2) + ",300)");
chartGroup
.selectAll("rect")
.data(newArray) // <-- use in-scope newArray value
.enter()
.append("rect")
.attr("height", (d, i) => d * 3)
.attr("width", "15")
.attr("fill", "blue")
.attr("x", (d, i) => 26.5 * i)
.attr("y", (d, i) => height - d * 3);
chartGroup
.selectAll("text")
.data(newArray) // <-- use in-scope newArray value
.enter()
.append("text")
.attr("font-size", 15)
.attr("x", (d, i) => 26.5 * i)
.attr("y", (d, i) => height - 5 - d * 3 + 2)
.text((d, i) => d);
chartGroup
.append("g")
.attr("class", "axis y")
// .attr('transform','translate(500,76)')
.call(yAxis);
chartGroup
.append("g")
.attr("class", "axis x")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
}
}, [chartData]);
const newArrayFunc = (a) => {
setYArray(a);
};
return (
<div id="chart-container">
<h3>Bar Chart</h3>
<svg className="svg-canvas" width="800px" height="400px"></svg>
</div>
);
};
更新状态并使用第二个效果更新d3
const Barchart = ({ chartData }) => {
let newArray = [];
let len = chartData.length;
const [XArray, setXArray] = useState([chartData]);
const [Yarray, setYArray] = useState(chartData[len - 1].anArray); //so the initial state here should be an empty array
// const d3Container = useRef(null);
useEffect(() => {
let len = chartData.length;
console.log(chartData.length);
newArray = chartData[len - 1].anArray;
setYArray(newArray);
}, [chartData]);
useEffect(() => {
if (Yarray.length) {
const height = 70; //height of the actual chart, different than the svg element
const width = 26.5 * Yarray.length; //width of the actual chart, different than the svg element
const svg = d3.select(".svg-canvas");
svg.selectAll("*").remove();
var x = d3.scaleLinear().domain([0, 7]).range([0, width]);
var y = d3
.scaleLinear()
.domain([0, d3.max(Yarray)])
.range([height, 0]);
var xAxis = d3.axisBottom(x).ticks(8);
var yAxis = d3.axisLeft(y).ticks(5);
//locate the chart in the middle of the svg frame: 800/2 - width/2
var chartGroup = svg
.append("g")
.attr("transform", "translate(" + (400 - width / 2) + ",300)");
chartGroup
.selectAll("rect")
.data(Yarray)
.enter()
.append("rect")
.attr("height", (d, i) => d * 3)
.attr("width", "15")
.attr("fill", "blue")
.attr("x", (d, i) => 26.5 * i)
.attr("y", (d, i) => height - d * 3);
chartGroup
.selectAll("text")
.data(Yarray)
.enter()
.append("text")
.attr("font-size", 15)
.attr("x", (d, i) => 26.5 * i)
.attr("y", (d, i) => height - 5 - d * 3 + 2)
.text((d, i) => d);
chartGroup
.append("g")
.attr("class", "axis y")
// .attr('transform','translate(500,76)')
.call(yAxis);
chartGroup
.append("g")
.attr("class", "axis x")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
}
}, [Yarray]);
const newArrayFunc = (a) => {
setYArray(a);
};
return (
<div id="chart-container">
<h3>Bar Chart</h3>
<svg className="svg-canvas" width="800px" height="400px"></svg>
</div>
);
};