在我的 React 项目上完成数据加载后如何执行我的代码
How can I execute my code after data load is finished on my react project
我正在使用图表 js 创建图表。我的问题是代码在数据加载之前是 运行,这就是我收到错误的原因。我希望在数据加载后执行代码,我使用了加载状态但它不起作用也使用了可选链接。
数据获取代码为
useEffect(() => {
setLoading(true)
fetch('./fakeDta.json')
.then(res => res.json())
.then(data => setSchedules(data))
.finally(() => setLoading(false))
}, [])
错误是
TypeError: Cannot convert undefined or null to object
TypeError: Cannot read properties of undefined (reading 'filter')
主要错误在这里:
const chart2 = schedulesByDate(date)
Object?.entries(chart2)?.map(
([key, value]) => {
dateLabels.push(key);
previousDateSchedules.push(value)
}
完整代码
import { Chart, registerables } from "chart.js";
import React, { useEffect, useRef, useState } from "react";
import { Bar } from "react-chartjs-2";
import './chart.css'
Chart.register(...registerables);
function BarChart() {
const inputRef1 = useRef()
const [date, setDate] = useState('')
const [laoding, setLoading] = useState(false)
// First chart date labels and value
let dateLabels = []
let previousDateSchedules = []
// Data
const [schedules, setSchedules] = useState()
useEffect(() => {
setLoading(true)
fetch('./fakeDta.json')
.then(res => res.json())
.then(data => setSchedules(data))
.finally(() => setLoading(false))
}, [])
// Bar chart option
let options = {
scales: {
y: {
max: 10,
ticks: {
stepSize: 1
}
}
}
};
// Chart 1 Function Start
const schedulesByDate = (date) => {
let dbItemDate = date;
let otherDayArray = schedules?.filter(num => num.item_date < dbItemDate);
let count = otherDayArray?.reduce(function (acc, num) {
acc[num.item_date] = (acc[num.item_date] || 0) + 1;
return acc;
}, []);
console.log(count);//this should print the frequency of each date in the others date array
return count
}
const chart2 = schedulesByDate(date)
Object?.entries(chart2)?.map(
([key, value]) => {
dateLabels.push(key);
previousDateSchedules.push(value)
}
)
// Chart 1 Function End
//function to get Chart 2 result
let getScheduleCounter = (date) => {
let scheduleCounter = {
'9_12': [],
'12_3': [],
'3_6': [],
'6_9': []
};
schedules.forEach(sch => {
if (sch.item_date === date) {
updateScheduledCounter(sch, scheduleCounter);
}
});
return scheduleCounter;
}
//function to get the count and update in scheduleCounter
let updateScheduledCounter = (sch, scheduleCounter) => {
let time = sch.schedule_time.split(' ')[1];
switch (!!time) {
case (time <= '12:00:00'):
scheduleCounter['9_12']++;
break;
case (time >= '12:00:00' && time <= '15:00:00'):
scheduleCounter['12_3']++;
break;
case (time >= '15:00:00' && time <= '18:00:00'):
scheduleCounter['3_6']++;
break;
case (time >= '18:00:00' && time <= '21:00:00'):
scheduleCounter['6_9']++;
break;
}
}
let schedulesTimes = []
let schedulesTimesValues = []
let schedule = getScheduleCounter(date);
console.log('schedules: ', schedule);
Object.entries(schedule).map(
([key, value]) => {
schedulesTimes.push(key);
schedulesTimesValues.push(value)
}
)
console.log(schedulesTimes, schedulesTimesValues);
return (
<>
{
laoding ? <h2>loading....</h2> : <div className="container">
<div className="bar">
<div classNam="chart-container" style={{ position: "relative", height: "550px", width: "40vw" }}>
<h2>Item Dates</h2>
<Bar
id="myChart"
data={{
labels: dateLabels,
datasets: [{
label: 'Scheduled',
data: previousDateSchedules,
backgroundColor: [
'rgba(255, 26, 104, 0.2)',
'rgba(54, 162, 235, 0.2)',
'rgba(255, 206, 86, 0.2)',
'rgba(75, 192, 192, 0.2)',
'rgba(153, 102, 255, 0.2)',
'rgba(255, 159, 64, 0.2)',
'rgba(0, 0, 0, 0.2)'
],
borderColor: [
'rgba(255, 26, 104, 1)',
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)',
'rgba(75, 192, 192, 1)',
'rgba(153, 102, 255, 1)',
'rgba(255, 159, 64, 1)',
'rgba(0, 0, 0, 1)'
],
borderWidth: 1
}]
}}
options={options}
/>
</div>
<div className="chart-container" style={{ position: "relative", height: "550px", width: "40vw" }}>
<h2>{date} Schedules</h2>
<Bar
id="myChart"
data={{
labels: ['9am to 12pm', '12pm to 3pm', '3pm to 6pm', '6pm to 9pm'],
datasets: [{
label: 'Scheduled',
data: schedulesTimesValues,
backgroundColor: [
'rgba(255, 26, 104, 0.2)',
'rgba(54, 162, 235, 0.2)',
'rgba(255, 206, 86, 0.2)',
'rgba(75, 192, 192, 0.2)',
'rgba(153, 102, 255, 0.2)',
'rgba(255, 159, 64, 0.2)',
'rgba(0, 0, 0, 0.2)'
],
borderColor: [
'rgba(255, 26, 104, 1)',
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)',
'rgba(75, 192, 192, 1)',
'rgba(153, 102, 255, 1)',
'rgba(255, 159, 64, 1)',
'rgba(0, 0, 0, 1)'
],
borderWidth: 1
}]
}}
options={options}
/>
</div>
</div>
<div>
<input type="date" ref={inputRef1} defaultValue='2021-05-18' />
<button onClick={() => setDate(inputRef1.current.value)}>Filter</button>
</div>
</div>
}
</>
);
}
export default BarChart;
一些可能导致问题的原因:
- 代码加载错误,您有
laoding
,但应该是 loading
。然而,这不太可能是个大问题,因为在将计划数据设置为获取结果之前,您仍会尝试访问代码中更高层的计划数据。
- 为了便于阅读,请更新您的三元组以包装以下结果:
<div className="container"> ...
括号内
fetch
函数是异步的,returns 是一个承诺,这意味着您必须将 fetch 调用包装在异步函数的 useEffect 中:
useEffect(()=>{
const fetchData = async () => {
fetch('./fakeDta.json')
.then(res => res.json())
.then(data => setSchedules(data))
.finally(() => setLoading(false))
};
fetchData();
},[])
- 根据您的使用效果,我会在对它执行操作之前检查日程表是否确实有数据(因为如果日程表为空,它会导致您遇到这些错误)- 类似于:
if(!schedule){
return <div>Loading</div>
}
我正在使用图表 js 创建图表。我的问题是代码在数据加载之前是 运行,这就是我收到错误的原因。我希望在数据加载后执行代码,我使用了加载状态但它不起作用也使用了可选链接。
数据获取代码为
useEffect(() => {
setLoading(true)
fetch('./fakeDta.json')
.then(res => res.json())
.then(data => setSchedules(data))
.finally(() => setLoading(false))
}, [])
错误是
TypeError: Cannot convert undefined or null to object
TypeError: Cannot read properties of undefined (reading 'filter')
主要错误在这里:
const chart2 = schedulesByDate(date)
Object?.entries(chart2)?.map(
([key, value]) => {
dateLabels.push(key);
previousDateSchedules.push(value)
}
完整代码
import { Chart, registerables } from "chart.js";
import React, { useEffect, useRef, useState } from "react";
import { Bar } from "react-chartjs-2";
import './chart.css'
Chart.register(...registerables);
function BarChart() {
const inputRef1 = useRef()
const [date, setDate] = useState('')
const [laoding, setLoading] = useState(false)
// First chart date labels and value
let dateLabels = []
let previousDateSchedules = []
// Data
const [schedules, setSchedules] = useState()
useEffect(() => {
setLoading(true)
fetch('./fakeDta.json')
.then(res => res.json())
.then(data => setSchedules(data))
.finally(() => setLoading(false))
}, [])
// Bar chart option
let options = {
scales: {
y: {
max: 10,
ticks: {
stepSize: 1
}
}
}
};
// Chart 1 Function Start
const schedulesByDate = (date) => {
let dbItemDate = date;
let otherDayArray = schedules?.filter(num => num.item_date < dbItemDate);
let count = otherDayArray?.reduce(function (acc, num) {
acc[num.item_date] = (acc[num.item_date] || 0) + 1;
return acc;
}, []);
console.log(count);//this should print the frequency of each date in the others date array
return count
}
const chart2 = schedulesByDate(date)
Object?.entries(chart2)?.map(
([key, value]) => {
dateLabels.push(key);
previousDateSchedules.push(value)
}
)
// Chart 1 Function End
//function to get Chart 2 result
let getScheduleCounter = (date) => {
let scheduleCounter = {
'9_12': [],
'12_3': [],
'3_6': [],
'6_9': []
};
schedules.forEach(sch => {
if (sch.item_date === date) {
updateScheduledCounter(sch, scheduleCounter);
}
});
return scheduleCounter;
}
//function to get the count and update in scheduleCounter
let updateScheduledCounter = (sch, scheduleCounter) => {
let time = sch.schedule_time.split(' ')[1];
switch (!!time) {
case (time <= '12:00:00'):
scheduleCounter['9_12']++;
break;
case (time >= '12:00:00' && time <= '15:00:00'):
scheduleCounter['12_3']++;
break;
case (time >= '15:00:00' && time <= '18:00:00'):
scheduleCounter['3_6']++;
break;
case (time >= '18:00:00' && time <= '21:00:00'):
scheduleCounter['6_9']++;
break;
}
}
let schedulesTimes = []
let schedulesTimesValues = []
let schedule = getScheduleCounter(date);
console.log('schedules: ', schedule);
Object.entries(schedule).map(
([key, value]) => {
schedulesTimes.push(key);
schedulesTimesValues.push(value)
}
)
console.log(schedulesTimes, schedulesTimesValues);
return (
<>
{
laoding ? <h2>loading....</h2> : <div className="container">
<div className="bar">
<div classNam="chart-container" style={{ position: "relative", height: "550px", width: "40vw" }}>
<h2>Item Dates</h2>
<Bar
id="myChart"
data={{
labels: dateLabels,
datasets: [{
label: 'Scheduled',
data: previousDateSchedules,
backgroundColor: [
'rgba(255, 26, 104, 0.2)',
'rgba(54, 162, 235, 0.2)',
'rgba(255, 206, 86, 0.2)',
'rgba(75, 192, 192, 0.2)',
'rgba(153, 102, 255, 0.2)',
'rgba(255, 159, 64, 0.2)',
'rgba(0, 0, 0, 0.2)'
],
borderColor: [
'rgba(255, 26, 104, 1)',
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)',
'rgba(75, 192, 192, 1)',
'rgba(153, 102, 255, 1)',
'rgba(255, 159, 64, 1)',
'rgba(0, 0, 0, 1)'
],
borderWidth: 1
}]
}}
options={options}
/>
</div>
<div className="chart-container" style={{ position: "relative", height: "550px", width: "40vw" }}>
<h2>{date} Schedules</h2>
<Bar
id="myChart"
data={{
labels: ['9am to 12pm', '12pm to 3pm', '3pm to 6pm', '6pm to 9pm'],
datasets: [{
label: 'Scheduled',
data: schedulesTimesValues,
backgroundColor: [
'rgba(255, 26, 104, 0.2)',
'rgba(54, 162, 235, 0.2)',
'rgba(255, 206, 86, 0.2)',
'rgba(75, 192, 192, 0.2)',
'rgba(153, 102, 255, 0.2)',
'rgba(255, 159, 64, 0.2)',
'rgba(0, 0, 0, 0.2)'
],
borderColor: [
'rgba(255, 26, 104, 1)',
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)',
'rgba(75, 192, 192, 1)',
'rgba(153, 102, 255, 1)',
'rgba(255, 159, 64, 1)',
'rgba(0, 0, 0, 1)'
],
borderWidth: 1
}]
}}
options={options}
/>
</div>
</div>
<div>
<input type="date" ref={inputRef1} defaultValue='2021-05-18' />
<button onClick={() => setDate(inputRef1.current.value)}>Filter</button>
</div>
</div>
}
</>
);
}
export default BarChart;
一些可能导致问题的原因:
- 代码加载错误,您有
laoding
,但应该是loading
。然而,这不太可能是个大问题,因为在将计划数据设置为获取结果之前,您仍会尝试访问代码中更高层的计划数据。 - 为了便于阅读,请更新您的三元组以包装以下结果:
<div className="container"> ...
括号内 fetch
函数是异步的,returns 是一个承诺,这意味着您必须将 fetch 调用包装在异步函数的 useEffect 中:
useEffect(()=>{
const fetchData = async () => {
fetch('./fakeDta.json')
.then(res => res.json())
.then(data => setSchedules(data))
.finally(() => setLoading(false))
};
fetchData();
},[])
- 根据您的使用效果,我会在对它执行操作之前检查日程表是否确实有数据(因为如果日程表为空,它会导致您遇到这些错误)- 类似于:
if(!schedule){
return <div>Loading</div>
}