问题描述
我正在为Chartjs
使用React包装器。我使用fetch API调用Nomics API来获取数据并将其存储在某些arrays
中。然后,我想在新的Chartjs实例中使用数组。除了渲染我的图表外,其他所有东西都起作用,我认为这是因为它是在诺言完成之前渲染的。我该如何只返回图表,直到对Nomics API的调用完成,或者在完成后对其进行更新?
这是我的组件:
import React from 'react';
import {Line} from 'react-chartjs-2';
const Day = () =>{
//starting price reiterated over the length of the data.
const zeroLine = [];
//stores all the increments of time
const timeLabels = [];
//List of all of the prices
const prices = [];
fetch("https://api.nomics.com/v1/currencies/sparkline?key=yadayadayada&ids=BTC&start=2020-04-14T00%3A00%3A00Z&end=2020-04-20T01%3A00%3A00Z",{}).then((res) => res.json())
.then((result) => {
for(var i = 0; i <= result[0].prices.length - 1; i++){
zeroLine.push(result[0].prices[0]);
timeLabels.push(result[0].timestamps[i]);
prices.push(result[0].prices[i]);
}
});
const chartData = {
labels: timeLabels,datasets: [
{
label: 'Price',fill: false,lineTension: 0,backgroundColor: 'rgba(75,192,1)',borderColor: 'rgba(0,borderWidth: 2,data: prices
},{
//Change this to create points for every time/date
label: '0 line',borderDash: [10,5],data: zeroLine,}
]
}
return(
<Line
data={chartData}
options={{
elements:{
point: {
radius: 0
}
},title:{
display:true,text:'BTC Price',fontSize:20
},legend:{
display:false,position:'right'
}
}}
/>
)
}
export default Day;
解决方法
您可以使用useState
和useEffect
钩子来实现此目的。
useEffect钩子可以用作componentDidMount(当您将依赖项数组作为[]传递时),componentDidUpdate(当您将值传递给依赖项数组时)和componentWillUnmount(当您具有第三个函数时)
另一方面,useState与使用setState相似。每当它更改时,都会触发组件重新渲染。
在您的情况下,我们现在要做的基本上是在获取响应时更新状态,这会触发重新渲染
import React,{useState,useEffect} from 'react';
import {Line} from 'react-chartjs-2';
const Day = () =>{
const [zeroLine,setZeroLine] = useState([]);
const [timeLabels,setTimeLabels] = useState([]);
const [prices,setPrices] = useState([]);
useEffect(() => {
fetch("https://api.nomics.com/v1/currencies/sparkline?key=yadayadayada&ids=BTC&start=2020-04-14T00%3A00%3A00Z&end=2020-04-20T01%3A00%3A00Z",{}).then((res) => res.json())
.then((result) => {
const zL = [];
const tL = [];
const p = [];
for(var i = 0; i <= result[0].prices.length - 1; i++){
zL.push(result[0].prices[0]);
tL.push(result[0].timestamps[i]);
p.push(result[0].prices[i]);
}
setZeroLine(zL);
setTimeLabels(tL);
setPrices(p);
});
},[]);
const chartData = {
labels: timeLabels,datasets: [
{
label: 'Price',fill: false,lineTension: 0,backgroundColor: 'rgba(75,192,1)',borderColor: 'rgba(0,borderWidth: 2,data: prices
},{
//Change this to create points for every time/date
label: '0 line',borderDash: [10,5],data: zeroLine,}
]
}
return(
<Line
data={chartData}
options={{
elements:{
point: {
radius: 0
}
},title:{
display:true,text:'BTC Price',fontSize:20
},legend:{
display:false,position:'right'
}
}}
/>
)
}
export default Day;
,
您可以使用useState
和useEffect
钩子以及条件渲染来做到这一点:
import React,useEffect} from 'react';
import {Line} from 'react-chartjs-2';
const Day = () =>{
// this piece of state will hold the data passed to the chart component once it returns from your fetch call.
const [chartData,setChartData] = useState(null);
const getChartData = () => fetch("https://api.nomics.com/v1/currencies/sparkline?key=yadayadayada&ids=BTC&start=2020-04-14T00%3A00%3A00Z&end=2020-04-20T01%3A00%3A00Z",{}).then((res) => res.json())
.then((result) => {
//starting price reiterated over the length of the data.
const zeroLine = [];
//stores all the increments of time
const timeLabels = [];
//List of all of the prices
const prices = [];
for(var i = 0; i <= result[0].prices.length - 1; i++){
zeroLine.push(result[0].prices[0]);
timeLabels.push(result[0].timestamps[i]);
prices.push(result[0].prices[i]);
}
const chartData = {
labels: timeLabels,datasets: [
{
label: 'Price',data: prices
},{
//Change this to create points for every time/date
label: '0 line',}
]
}
setChartData(chartData)
});
useEffect(getChartData,[])
return chartData ? (
<Line
data={chartData}
options={{
elements:{
point: {
radius: 0
}
},position:'right'
}
}}
/>
) : <p>loading...</p>
}
export default Day;