Reputation: 466
So, I've been reacting for quite some time. I am facing a problem handling API and making it interact with small widgets in mobile app.
What I am trying to do ?
I am on a Screen(A) and on click of a button I go to Screen(B). Simple. Now in Screen(B) I fill up a form and submit it. While the form is submitting I have to show a Loading
component. Finally the API responds if the request was "Success" or a "Failure".
If it was Success - Navigate back to Screen(A) and show a toast message(Boom..boom..) on screen(A).
If it Failed - Be in Screen(B) and show a toast message(yes, with a failure message).
My Approach
Let's start with reducers. I have following reducer state -
{
forSubmitRequest: false, // false - API has been trigerred to submit form
formSubmitRequestOver: true, // true - request is over
formSubmitRequestStatus: true // true - success
}
Now my actions are as follows -
case FORM_SUBMIT_REQUEST:
return {
...state,
formSubmitRequest: true,
formSubmitRequestOver: false,
formSubmitRequestStatus: false,
};
case FORM_SUBMIT_REQUEST_SUCCESS:
return {
...state,
formSubmitRequestOver: true,
formSubmitRequestStatus: true
};
case FORM_SUBMIT_REQUEST_FAILED:
return {
...state,
formSubmitRequestOver: true,
formSubmitRequestStatus: false,
};
case FORM_SUBMIT_REQUEST_DOWN:
return {
...state,
formSubmitRequest: false,
formSubmitRequestOver: true
};
Here's my coding logic in Screen(B)
const [formSubmitReq, setFormSubmitReq] = useState(false);
const [showErrorFormSubmitToast, setShowErrorFormSubmitToast] = useState(false);
useEffect(() => {
if (showErrorFormSubmitToast) {
Toast.show({
type: 'error',
text1: 'Error',
text2: 'Could not submit.',
topOffset: ResponsiveSize(0),
onHide: () => {
setShowErrorFormSubmitToast(false);
},
});
}
}, [showErrorFormSubmitToast]);
if (
formSubmitReq &&
props.teacher.formSubmitRequest &&
!props.teacher.formSubmitRequestOver
) {
return <Loading msg="Submitting form..." />;
}
if (
formSubmitReq &&
props.teacher.formSubmitRequest &&
props.teacher.formSubmitRequestOver
) {
if (props.teacher.formSubmitRequestStatus) {
props.navigation.goBack();
return <></>;
} else {
setFormSubmitReq(false);
setShowErrorFormSubmitToast(true);
props.handleCreateFormSubmitDown();
}
}
Logic in Screen(A)
const [showSuccessFormSubmitToast, setShowSuccessFormSubmitToast] =
useState(false);
useEffect(() => {
if (showSuccessFormSubmitToast) {
Toast.show({
type: 'success',
text1: 'Success',
text2: 'Successfully submitted.',
onHide: () => {
setShowSuccessFormSubmitToast(false);
},
});
}
}, [showSuccessFormSubmitToast]);
if (
!showSuccessFormSubmitToast &&
props.teacher.formSubmitRequest &&
props.teacher.formSubmitRequestOver &&
props.teacher.formSubmitRequestStatus
) {
console.log('Prep show toast');
setShowSuccessFormSubmitToast(true);
props.handleCreateFormSubmitDown();
}
Lastly this function - handleCreateFormSubmitDown
just fires action - FORM_SUBMIT_REQUEST_DOWN
Gist of the code ->
I am trying to show Toast on Screen(A) only when request was success and request was actually fired. Not it may happen that request was success and I came back to Screen(A) now I simply navigate to Screen(B) so I have to make sure toast isn't visible as request wasn't fired. Now when reducer state updates then Screen(A) also gets rendered causing some nast things.
Can anyone point out what strategies they follow in such scenarios and where I could improve here?
Upvotes: 0
Views: 1931
Reputation: 386
One way to do this is to utilize route params from react-navigation
In screen B
...
useEffect(() => {
// Navigate to screen A with a route param
navigation.navigate(A, { displaySuccessToast: true });
}, [showSuccessFormSubmitToast])
In Screen A
...
useEffect(() => {
if (route.params.displaySuccessToast) {
Toast.show({
type: 'success',
text1: 'Success',
text2: 'Successfully submitted.',
onHide: () => {
// Hide Toast Action
},
});
}
}, [route.params]);
Other wise you can use a global state management solution like redux
Its the same logic. You need to update a flag in the global state. Then navigate to the earlier screen and check if this flag is set and render the toast message.
Upvotes: 1