React JS Reducer - Not Able To Do Anything With The Returned Payload, Only Able To Print
I'm struggling with this issue for a few days straight now.
My reducer file:
import {ADD_REPORT, GET_REPORTS, GET_REPORTS_ERROR, GET_REPORTS_SUCCESS} from "./ReportActions";
export const INITIAL_STATE = {
reports: [],
isFetching: false,
error: ''
};
export default function reportReducer(state = INITIAL_STATE, action) {
switch (action.type) {
case GET_REPORTS:
return{
...state,
isFetching: true,
error: ''
};
case GET_REPORTS_SUCCESS: // This is the part it's about.
return {
...state,
isFetching: false,
reports: action.payload.reports,
count: action.payload.reports.length
};
case GET_REPORTS_ERROR:
return {
...state,
isFetching: false,
error: action.payload.error
};
case ADD_REPORT:
return {...state,
reports: [...state.reportStore.payload,
{
id: action.report.id,
date: action.report.date,
city: action.report.city,
status: action.report.status
}]
};
default:
return state;
}
}
My output:
As you can see, I'm not able to do anything with action.payload.reports
or it will become empty.
The data is being fetched through React Saga, sent to the action and handled by the reducer.
When using hardcoded mock data that's following it does work:
case GET_REPORTS_SUCCESS:
return {
...state,
isFetching: false,
reports: [{"id":14,"date":"24-10 13:28","city":"blabla","status":"unfixed"}],
count: [{"id":14,"date":"24-10 13:28","city":"blabla","status":"unfixed"}].length
};
I'd appreciate any help!
Answer
Problem solved!
Reporting back after researching what was wrong. The problem was that I returned an array before it was done fetching.
First I used yield call to make a fetch API request in another component, and use the result to work with. (ReportSagas.js)
//Warning: This is not the solution, I'm explaining my fault first!
import { takeLatest, all, call, put } from 'redux-saga/effects';
import ReportService from '../../api/ReportList';
import {GET_REPORTS, getReportsSuccess, getReportsError} from "./ReportActions";
export function* getReportsSaga() {
try {
console.log("ReportSagas.js -> getReportsSaga() Try {}");
const data = yield call(ReportService.getReports);
yield put(getReportsSuccess(data));
return data;
} catch(error) {
console.log("ReportSagas.js -> getReportsSaga() Catch {}");
yield put(getReportsError(error));
return error;
}
}
export function* watchGetReports() {
yield all([takeLatest(GET_REPORTS, getReportsSaga)]);
}
The Fetch request looked like this. And as you can see, the "reports" array was outside the scope and I returned it before the fetch was even finished. (api/ReportList.js)
//Warning: This is not the solution, I'm explaining my fault first!
class ReportService {
getReports = async () => {
let reports = [];
fetch('https://xxx/')
.then(response => response.json())
.then(function(jsonResp) {
jsonResp.forEach(function(reportItem) {
let report = {id: reportItem, date: reportItem.date, city: reportItem.city, status: reportItem.status};
reports.push(report);
});
});
return reports;
}
}
export default new ReportService();
So the solution I simply came up with, is to make the fetch request within the Sagas file like this, and it works fine! (ReportSagas.js)
import { takeLatest, all, call, put } from 'redux-saga/effects';
import {GET_REPORTS, getReportsSuccess, getReportsError} from "./ReportActions";
export function* getReportsSaga() {
try {
console.log("ReportSagas.js -> getReportsSaga() Try {}");
let data = yield fetch(`http://xxx/`);
data = yield data.json();
yield put(getReportsSuccess(data));
return data;
} catch(error) {
console.log("ReportSagas.js -> getReportsSaga() Catch {}");
yield put(getReportsError(error));
return error;
}
}
export function* watchGetReports() {
yield all([takeLatest(GET_REPORTS, getReportsSaga)]);
}
Related Questions
- → How to update data attribute on Ajax complete
- → October CMS - Radio Button Ajax Click Twice in a Row Causes Content to disappear
- → Octobercms Component Unique id (Twig & Javascript)
- → Passing a JS var from AJAX response to Twig
- → Laravel {!! Form::open() !!} doesn't work within AngularJS
- → DropzoneJS & Laravel - Output form validation errors
- → Import statement and Babel
- → Uncaught TypeError: Cannot read property '__SECRET_DOM_DO_NOT_USE_OR_YOU_WILL_BE_FIRED' of undefined
- → React-router: Passing props to children
- → ListView.DataSource looping data for React Native
- → Can't test submit handler in React component
- → React + Flux - How to avoid global variable
- → Webpack, React & Babel, not rendering DOM