如何解决setState在useEffect中的问题导致状态更改延迟
我正在使用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',i)=>26.5*i)
.attr('y',i)=>height-d*3)
chartGroup.selectAll('text').data(Yarray).enter().append("text")
.attr('font-size',15)
.attr('x',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条形图中使用。
我在这里应该做什么?
解决方法
选项1
继续使用与更新状态相同的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",i) => 26.5 * i)
.attr("y",i) => height - d * 3);
chartGroup
.selectAll("text")
.data(newArray) // <-- use in-scope newArray value
.enter()
.append("text")
.attr("font-size",15)
.attr("x",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>
);
};
选项2
更新状态并使用第二个效果更新d3
const Barchart = ({ chartData }) => {
let newArray = [];
let len = chartData.length;
const [XArray,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,d3.max(Yarray)])
.range([height,300)");
chartGroup
.selectAll("rect")
.data(Yarray)
.enter()
.append("rect")
.attr("height",i) => height - d * 3);
chartGroup
.selectAll("text")
.data(Yarray)
.enter()
.append("text")
.attr("font-size",[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>
);
};
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。