I have 100+ <td>
to render. I'm fetching it using NodeJS backend, passing the data to the frontend, and using Redux to React components.
I have many components that render fewer data and everything works great, but when it comes to this component, nothing happens until I refresh the page.
I tried using different life cycles (cpmponentWillMount, willRecieveProps, etc), but nothing seems to work.
I'm also using React-thunk and react-router
After the first refresh, there is no need for that anymore. So basically it only occurs when I first start the dev server.
I strongly believe that I have to use one of the component lifecycle functions and that I tried the wrong ones or in the wrong order?
ReportsData == > Where the rendering happens
class ReportsData extends Component {
constructor(props) {
super(props);
this.state = {
allReports: []
}}
getReportsData = () => {
return reportsApi.getReports().then(report => {
this.setState(() => ({
allReports: Object.assign([], report.data)
})
)});
}
componentWillMount() {
this.getReportsData(this.props);
}
render() {
// const { reports } = this.props;
const { allReports } = this.state;
let sortedReports = _.sortBy(reports, function(o) { return new moment(o.date) }).reverse();
const listReports = sortedReports.map(item => {
return (
<tr key={item.rowNumber}>
<td> {item.year}</td>
<td> {item.month}</td>
<td> {item.bruto_ukupno}</td>
<td> {item.neto_plata}</td>
<td> {item.topli_obrok}</td>
<td> {item.doprinosi}</td>
<td> {parseInt(item.ukupno_plata, 10)}</td>
<td className="table-actions">
<Link to={{ pathname: '/reports/details', state: { item } }}>
<PieChart size="21"/>
</Link>
</td>
</tr>
)});
return (
<div className="portlet-body">
<table className="table table-striped">
<thead>
<tr>
<th>Year</th>
<th>Month</th>
<th>Gross</th>
<th>Net</th>
<th>Meals</th>
<th>Taxes</th>
<th>Salarys</th>
<th>Details</th>
</tr>
</thead>
<tbody>
{listReports}
</tbody>
</table>
</div>
);
}
}
ReportsAPI
import axios from 'axios';
import {baseApiUrl} from '../config/config';
const reportsApiUrl = baseApiUrl + 'reports/'
class ReportsApi {
static getReports() {
return axios({
method: 'get',
url: reportsApiUrl + 'getReports'
})
}
}
export default ReportsApi;
reportsActions
import * as actionTypes from '../actionTypes/actionTypes';
import ReportsApi from "../api/reportsApi";
export const getReports = (data) => {
return {
type: actionTypes.GET_REPORTS,
data
}
}
export const getReportsAsync = () => {
return dispatch => {
return ReportsApi.getReports()
.then(reports => {
dispatch(getReports(reports.data));
}).catch(error => {
console.log('error while loading reports', error);
throw(error);
});
};
}
This happens only the first time I start the DEV server So when I lift app my app every other component receives it's props, except this one, and I'm using the same logic everywhere.The only difference is in the amount of data being rendered. If I log out and log back in, everything is perfectly fine. If I refresh, go back and forward, it's all good, but as soon as i stop the server, start it again, only this component has that issue.
There was an unnecessary check if data coming from the API was undefined and Redux has to wait for the needed data. By the time that checks out, the component is already rendered without any data. I rearranged the code a little bit and now it's working. Thanks for pointing me in the right direction.
So, the issue was on the backend in the reportsService module.
Here's the fix for future reference:
const _ = require('lodash');
module.exports = {
mapReportsSheetToJson(data) {
let result = [];
for (let i = 2; i < data.length; i++) {
let elem = {};
data[1].map((item, index) => {
// if (typeof data[i][index] !== 'undefined') {
elem[item.toLocaleLowerCase()] = data[i][index];
// }
})
elem['rowNumber'] = i + 1;
result.push(elem);
}
return result;
}
}