I was able to achieve the following -> When a user clicks on a particular date in component A the data gets sent to the Node (Sails API) where all the necessary calculations are done, and before component B is rendered the correct data is ready to be shown.
The problem is when a user returns back from component B to component A and chooses a different date, he/ she gets the exact same result (old value) because even though the new value is sent to the backend API, Node isn't doing the recalculations with the new value.
I'm only able to achieve the correct result after I manually refresh the page, or make changes to the server so it forces the recalculation.
I think I need to mention that I'm passing data using Redux, so maybe the issue occurs on that part.
I would consider some type of auto refresh, animated loading, anything. Yup, so stuck :/
Is it even possible to make them in total sync?
UPDATE --> Here is the code:
BACKEND
getDetails: (req, res) => {
authentication.authenticate().then((auth) => {
const sheets = google.sheets('v4');
sheets.spreadsheets.values.get({
auth: auth,
spreadsheetId: config.spreadsheetSettings.spreadsheetId, // id of spreadsheet
range: config.spreadsheetSettings.employeeSheetId, // name of employee spreadsheet and range- get all cells
}, (err, response) => {
if (err) {
res.serverError(err);
return;
}
const rows = response.values; // response-all cells
const updatedData = employeeService.mapEmployeeSheetToJson(rows);
// FETCHING THE VALUE FROM REST API
let myArr = [];
(function() {
axios.get(`http://localhost:1337/api/`)
.then(res => {
let kajmak = res.data.slice(-1)[0]
let test = kajmak[Object.keys(kajmak)[0]]
myArr.push(test)
}).catch(err => console.error(err));
})();
// MAPING OVER THE ARRY AND DOING THE LOGIC
setTimeout(() => {
myArr.map(xo => {
const result = [];
updatedData.forEach(emp => {// 2013 2012 2014
if (xo > parseInt(moment(emp.startdate).format('YYYYMM'), 10) &&
(xo < parseInt(moment(emp.enddate).format('YYYYMM'), 10))) {
result.push(emp);
}
});
// IF THEY STARTED WORKING BEFORE THE SELECTED DATE AND STILL WORKING
updatedData.forEach(emp => { // 2013 > 2012 & 2013 -
if (xo > parseInt(moment(emp.startdate).format('YYYYMM'), 10) &&
((parseInt(moment(emp.enddate).format('YYYYMM'), 10) == undefined ))) {
result.push(emp);
}
});
// IF THEY STARTED WORKIG BEFORE THE SELECTED DATE,
// BUT STOPPED WORKING BEFORE THE SELECTED DATE
updatedData.forEach(emp => { // 2013 < 2014 || 2013 > 2017
if (xo < parseInt(moment(emp.startdate).format('YYYYMM'), 10) &&
(xo > parseInt(moment(emp.startdate).format('YYYYMM'), 10))) {
result.pop(emp);
}
});
// Getting the names to use for unique sheet req
let finalResult = [];
result.map(x => {
finalResult.push((x.name + ' ' + x.surname))
})
if (rows.length === 0) {
res.err('No data found.');
} else {
res.ok(finalResult);
}
})
}, 1000);
});
}
FRONTEND
getEmployeeSalaryData = () => {
// GETTING THE CLICKED VALUE FROM THE PREVIOUS COMPONENT
const { year } = this.props.history.location.state.item;
const { month } = this.props.history.location.state.item;
const selectedMonth = moment().month(month).format("MM");
const finalSelect = parseInt(year + selectedMonth, 10);
const { employees } = this.props;
// I'M RECIEVING THIS AS PROPS USING REDUX AND THIS IS THE ACTUAL 'FINAL' DATA USED FOR FURTHER CALCS AND RENDERING
const { details } = this.props;
// HERE I'M SENDING THE 'CLICKED' VALUE FROM THE PREVIOUS COMPONENT TO THE BACKEND API
axios.post(`http://localhost:1337/api/`, { 'test' : finalSelect })
.then(res => {
console.log('Data send')
// console.log(res.data);
}).catch(err => console.error(err));
// Making the req
details.map(x => {
EmployeeApi.getEmployee(x)
.then(y => {
//Making sure everything is in the right order
let test = Object.assign(y.data);
let ii = x;
setTimeout(
this.setState(prevState => ({
...prevState.currentEmployee,
fullNames: [...prevState.currentEmployee.fullNames, ii]
})), 100);
let onlyRelevantDate = [];
test.map(item => {
if (finalSelect == parseInt(item.year + moment().month(item.month).format("MM"), 10)) {
onlyRelevantDate.push(item)
}})
this.setState(prevState => ({
currentEmployee: {
...prevState.currentEmployee,
salaryInfo: [...prevState.currentEmployee.salaryInfo, onlyRelevantDate],
fullNames: [...prevState.currentEmployee.fullNames, ii]
}}))
})
});
}
componentWillReceiveProps(nextProps) {
this.getEmployeeSalaryData(nextProps);
}
componentWillMount() {
this.getEmployeeSalaryData(this.props);
}
In component A you should dispatch an action that is a function taking a dispatch function.
//some click handler for when user makes a selection
// the function should be in action creator file but you get the jist
const handleSomeClick = someValue =>
//when you dispatch an action that is a function in redux with thunk then
// the thunk middleware will not call next (no reducers will be called)
// thunk will pass a parameter to this function that is the dispatch
// function so from your function you can dispatch actual object action(s)
dispatch(
dispatch=>
setTimeout(
dispatch({type:"changedValue",data:someValue}),//dispatching the action
someValue*1000//assuming someValue is a number
)
)
Here is an example that has component A set someValue
depending on what button is clicked and will highlight that button it'll also set someValue
of B asynchronously. This is done in the function changeLater
that dispatches an action that is a function so thunk will execute it with the dispatch.
This function will dispatch an action after a timeout. If you click the numbers 5 and then 1 (quickly) you'll see that the highlighted button of A and value after async of B do not match (highlighted of A is 1 and value after async of B is showing 5).
This is because the order of which the user clicks and starts the async process is not the same as the order the async process resolves. You could solve this by only dispatching an action when it's the last resolved promise.
This example shows how it's done by using a promise created by later
and only resolve it if it's the last by using a partially applied version of onlyLastRequestedPromise
called lastNumberClicked
您可以使用RxJS解决此问题
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.