如何在 React 返回 promise 后才绘制图表?
How do I draw chart only after promise is returned in React?
我正在为 Chartjs
使用 React 包装器。我使用 fetch API 调用 Nomics API 来获取数据并将其存储在一些 arrays
中。然后我想在新的 Chartjs 实例中使用数组。除了我的图表呈现外,一切正常,我认为这是因为它在承诺完成之前呈现。在对 Nomics API 的调用完成之前,我如何只 return 图表或在完成后更新它?
这是我的组件:
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,192,1)',
borderColor: 'rgba(0,0,0,1)',
borderWidth: 2,
data: prices
},
{
//Change this to create points for every time/date
label: '0 line',
fill: false,
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。它会在组件发生变化时触发组件 re-render。
在你的情况下,我们现在所做的基本上是更新获取响应的状态,这会触发重新渲染
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,192,1)',
borderColor: 'rgba(0,0,0,1)',
borderWidth: 2,
data: prices
},
{
//Change this to create points for every time/date
label: '0 line',
fill: false,
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, {useState, 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',
fill: false,
lineTension: 0,
backgroundColor: 'rgba(75,192,192,1)',
borderColor: 'rgba(0,0,0,1)',
borderWidth: 2,
data: prices
},
{
//Change this to create points for every time/date
label: '0 line',
fill: false,
borderDash: [10,5],
data: zeroLine,
}
]
}
setChartData(chartData)
});
useEffect(getChartData, [])
return chartData ? (
<Line
data={chartData}
options={{
elements:{
point: {
radius: 0
}
},
title:{
display:true,
text:'BTC Price',
fontSize:20
},
legend:{
display:false,
position:'right'
}
}}
/>
) : <p>loading...</p>
}
export default Day;
我正在为 Chartjs
使用 React 包装器。我使用 fetch API 调用 Nomics API 来获取数据并将其存储在一些 arrays
中。然后我想在新的 Chartjs 实例中使用数组。除了我的图表呈现外,一切正常,我认为这是因为它在承诺完成之前呈现。在对 Nomics API 的调用完成之前,我如何只 return 图表或在完成后更新它?
这是我的组件:
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,192,1)',
borderColor: 'rgba(0,0,0,1)',
borderWidth: 2,
data: prices
},
{
//Change this to create points for every time/date
label: '0 line',
fill: false,
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。它会在组件发生变化时触发组件 re-render。
在你的情况下,我们现在所做的基本上是更新获取响应的状态,这会触发重新渲染
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,192,1)',
borderColor: 'rgba(0,0,0,1)',
borderWidth: 2,
data: prices
},
{
//Change this to create points for every time/date
label: '0 line',
fill: false,
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, {useState, 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',
fill: false,
lineTension: 0,
backgroundColor: 'rgba(75,192,192,1)',
borderColor: 'rgba(0,0,0,1)',
borderWidth: 2,
data: prices
},
{
//Change this to create points for every time/date
label: '0 line',
fill: false,
borderDash: [10,5],
data: zeroLine,
}
]
}
setChartData(chartData)
});
useEffect(getChartData, [])
return chartData ? (
<Line
data={chartData}
options={{
elements:{
point: {
radius: 0
}
},
title:{
display:true,
text:'BTC Price',
fontSize:20
},
legend:{
display:false,
position:'right'
}
}}
/>
) : <p>loading...</p>
}
export default Day;