I created a chart in React app with react-chartjs-2. I have 2 items on the homepage: "chart1" and "chart2". When I click on the "chart1" - chart displays with no data. After second click, data are rendering correctly. Next I want to render "chart2", but after click on that item, "chart1" renders. After second click, data for "chart2" are rendering correctly. Do you know what is the problem? I want to render every chart after first click.
Chart.js
import React, { useEffect, useState } from 'react';
import { connect } from 'react-redux';
import { Line } from 'react-chartjs-2';
import { getChartData } from '../../actions/sensors';
const Chart = (props) => {
const [chartDataState, setChartDataState] = useState({});
const createChart = () => {
const id = props.match.params.id;
props.getChartData(id);
setChartDataState({
labels: props.chartData.map(data => {
const date = new Date(data.delivery_time).toLocaleDateString();
const time = new Date(data.delivery_time).toLocaleTimeString();
return `${time} | ${date}`;
}),
datasets: [
{
data: props.chartData.map(data => data.sensor_data),
fill: false,
backgroundColor: '#987316',
borderColor: 'rgba(152, 115, 22, 0.2)',
},
],
})
}
useEffect(() => {
createChart();
}, [])
return (
<div className="container">
<div className="head" style={{'marginBottom': '30px'}}>
<h2>Chart</h2>
<div className="line" style={{"width": "900px"}}></div>
</div>
<div className="chart">
<Line
data={chartDataState}
options={{
maintainAspectRatio: false,
legend: {
display: false,
}
}}
height={400}
/>
</div>
</div>
);
}
const mapStateToProps = state => ({
chartData: state.sensors.chartData,
})
export default connect(mapStateToProps, { getChartData })(Chart);
sensors (Redux action)
export const getChartData = id => (dispatch, getState) => {
const token = getState().auth.token;
const config = {
headers: {
'Content-Type': 'application/json',
'Authorization': `Token ${token}`
}
}
axios.get(`${baseURL}/sensors_data/list/${id}`, config)
.then(res => {
dispatch({
type: GET_CHART_DATA,
payload: res.data
})
})
.catch(err => console.log(err))
}
sensors (Redux reducer)
import { GET_CHART_DATA } from '../actions/types';
const initialState = {
chartData: [],
}
export default function(state = initialState, action) {
switch(action.type) {
case GET_CHART_DATA:
return {
...state,
chartData: action.payload
}
default:
return state;
}
When you first click, you trigger a request for the data, but your component does not wait for that data before rendering.
I would recommend adding a condition to your return. This is how I would have done it without Redux (I've never used Redux)
return (
<div className="container">
<div className="head" style={{'marginBottom': '30px'}}>
<h2>Chart</h2>
<div className="line" style={{"width": "900px"}}></div>
</div>
<div className="chart">
{chartDataState.length > 0 ?
<Line
data={chartDataState}
options={{
maintainAspectRatio: false,
legend: {
display: false,
}
}}
height={400}
/>
: <div>Loading...</div>}
</div>
</div>
);
Basically: you don't want your component to render the chart before the data is returned.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.