Show a message when I submit a form - javascript

I'm building a site for a project,I have a divided into 50% 50% with display grid, on the right side there is the form, once sent I would like it to show a confirmation or error message , what can I do? i am using nextjs
the form must disappear and show the message
i could use display none, is there a better method? maybe using the components. Thank you

Well if it were me, ill create a separate feedback component and once the form is submitted, ill send a response be it an error message or success message.
And maybe add a close button plus a timer to close the component.

You can use React portals to access the right side of your app from the left side and render components in it.
I would create a Notification component.
const Notification = ({ message, hideAfterMs }) => {
const [visible, setVisible] = React.useState(true);
React.useEffect(() => {
const timeout = setTimeout(() => { setVisible(false); }, hideAfterMs);
return () => {
clearTimeout(timeout);
}
}, [setVisible]);
if(visible)
return <div>Notification: {message}</div>
return null;
}
Use the portal to render a notification on the side of your app.

Related

Element of a screen still found by getByTestID after navigating on another screen

I hope I am not spamming too much... Actually, I deleted my previous questions to make this one and keep it small and up to the point.
I have a react native application built with expo with a Home screen with one button. Using a stack navigator, this button can enable users to access Screen1. I want to test the following scenario, using jest and #testing-library/react-native :
When the user clicks on the "go to screen1" button, he is sent to Screen1.
So I did this :
it(
'should take user to Screen1 when go-to-screen1 button is pressed',
async () => {
const navigate = jest.fn();
const { getByTestId } = render(<HomeScreen navigation={{ navigate }} />);
fireEvent.press(getByTestId('go-to-screen1-btn'));
waitFor(() => expect(getByTestId('screen1')).toBeTruthy());
},
);
This test succeeds.
But this one succeeds also :
it(
'should take user to Screen1 when go-to-screen1 button is pressed',
async () => {
const navigate = jest.fn();
const { getByTestId } = render(<HomeScreen navigation={{ navigate }} />);
fireEvent.press(getByTestId('go-to-screen1-btn'));
waitFor(() => expect(getByTestId('go-to-screen1-btn')).toBeTruthy());
},
);
Like if the elements on the first page still exists whereas we have moved on another page...
The waitFor is in order to wait for the page change, I tried to remove it but the first test fails if it is removed.
Here is a github repo with the code I describe.
Does someone have an idea ?
Thanks in advance for any help !

How to work with multiple tabs using react-idle-timer

I am having a react Application, where I need to display a modal with two buttons (Logout and Continue Session) when the user goes idle, It was actually working fine with the IdleTimer component from the react-idle-timer.
But If I open the Application in multiple tabs, and click on Continue session in one tab, the other tabs are not receiving that, The sample code that I have used is,
<IdleTimer
timeout={1000}
onIdle={// Opens a modal with two buttons Logout and Continue Session}
></IdleTimer>
Is it possible to use the crossTab prop? but I am not sure how to implement them.
How can I achieve my requirement to work with multiple tabs so that if I click on continue session all the tabs need to close the modal.
The version I am using is - react-idle-timer (4.6.4)
Could someone please help with this to achieve my requirement? Thanks in advance!!
You can use the Cross Tab Messaging feature from the documentation:
// Action dispatcher (redux)
const dispatch = useDispatch()
// Message handler
const onMessage = data => {
switch (data.action) {
case 'LOGOUT_USER':
dispatch(logoutAction())
break
// More actions
default:
// no op
}
}
// IdleTimer instance
const { message } = useIdleTimer({ onMessage })
// Logout button click
const onLogoutClick = () => {
// Tell all tabs to log the user out.
// Passing true as a second parameter will
// also emit the event in this tab.
message({ action: 'LOGOUT_USER' }, true)
}
See the documentation for v5, here.

React Formik change validation when auto submitting

I have a multistep form with a submit button at the bottom of each section and a clickable list of the sections for navigation. I have implemented an auto submit feature that runs if a user updates information and then navigates away using the menu without clicking the submit button:
const AutoSubmit = () => {
const { dirty, submitForm } = useFormikContext();
React.useEffect(() => {
if (dirty) {
submitForm();
}
}, [dirty, submitForm]);
return null;
};
The issue is that if the Yup validation fails then the submission is obviously blocked and any information on the previous section is lost. Essentially what i'm trying to do is trigger full validation if a user clicks the actual submit button, but do a partial validation (i.e. no required fields) if its an auto submit so their progress can be saved.
Ive tried using setFieldValue to set an "autoSubmit: true" flag in the above component and then changed the Yup Schema to only require fields etc if its not there or false, but it doesn't seem to pick up the value in time for the submission (presumably something to do with it running when the component is unmounting). Anyone got any ideas on how to get this working?
Thanks
So i had a bit of a rethink of this and thought i should post my solution just in case anyone finds it useful. I essentially decided to bypass the Formik validation for the partial submit, and let the backend handle it. As this was going to be a silent submit, the user feedback of the validation wasn't required, and because its assuming some data may be missing etc, it seems like something the backend should be deciding on.
The only other problem was that Formik re-renders every time any of the form data changes. My requirement was to only trigger this partial submit when the user navigated away from the form section, so my example above wasn't suitable as it would fire on every re-render. To get around this i used a ref and put the function outside of Formik:
function FormComponent() {
const formRef = useRef();
useEffect(() => {
return async () => {
const {dirty, isSubmitting, values} = formRef.current;
if (!isSubmitting && dirty) {
try {
await doPartialSubmission(values);
} catch (error) {
// Handle error
}
}
};
}, [formRef])
return (
<Formik
innerRef={formRef}
onSubmit={doFullValidatedSubmit()}
>
//Standard formik stuff...
</Formik>
);
};

How to make a modal toggle only when navigating from a specific page in React Native?

I have two screens in my app called "ReadyScreen" and "RunningScreen."
The user can access ReadyScreen on one of two ways:
1: When they are getting ready to start a run (when they click the start run button)
2: When they finish the run, they will be navigated from RunningScreen back to the ReadyScreen.
When the user finishes a run, i want a modal to toggle showing them:
How Many Steps They Ran, Average HR, etc.
but I only want it to toggle when they are navigating from "RunningScreen."
Would this require an "if" statement basically stating if they navigated from RunningScreen the modal will toggle, else, it will not? Or is there more nuance to this?
i would send a route param in RunningScreen:
navigation.navigate('ReadyScreen', {
didComeFromRunningScreen: true
})
then in RunningScreen get the variable:
const RunningScreen = ({ route }) => {
const { didComeFromRunningScreen } = route.params
useEffect(() => {
if(didComeFromRunningScreen){
//show modal
}
}, [])
}
i believe this should work.

Redux middleware is half working but not fully cancelling action

I have some simple middleware that is kind of working but also not working
basically I have a list of users and I am trying to delete one. and then sync it up with firebase. all is well.
I'm adding some middleware so that when a user deletes one it asks if you are sure? (just using a simple alert for now). if you click cancel, it doesn't delete. if you click ok it does
so far, that is working but because of my action creators it still carrying on and deleting the user. here is some code:
// click to delete user
<button
onClick={() =>
this.props.deleteUserFromStoreThenUpdateFirebase(user)
}
>
calls this method
I think something funky is going on here, basically it shouldn't call the deletedUserFromFirebase method if I hit cancel
export const deleteUserFromStoreThenUpdateFirebase = user => {
return (dispatch, getState) => {
return dispatch(deleteUser(user)).then(() => {
return deleteUserFromFirebase(user);
})
};
};
export const deleteUser = user => {
return async dispatch => {
dispatch({ type: DELETE_USER, user: user, reqConfirm: true });
};
};
middleware:
const confirmMiddleware = store => next => action => {
if(action.reqConfirm){
if(confirm('are you sure?')){
next(action)
}
}
else {
next(action)
}
}
I also think that confirmation actions should be [only] role of the UI.
Redux store can (should?) be treated like API - request (action) > response (changed state). Are you sending request to an API and waiting to confirmation message? It would be at least strange.
But I see even more than some sense in this idea. Centralised confirmation element can have a similiar role to toasts/snackbar messages.
Problem #1: There is a strict separation between UI and store logic - you can't use middleware to show dialog. But you can change state which can used in UI to show confirmation dialog.
Problem #2: There is no simple if/then/return chain of actions, you have to buffer an action and run it after confirmation (receiving 'confirm' action) or drop it on cancel. Yes, it can be done as middleware.
IDEA:
Action dispatched as requiring confirmation is saved in buffer. You can then change action type to CONFIRM_SHOW - state will be changed, props passed, modal dialog can be shown.
On CONFIRM_OK run buffered action, next steps will be common with CONFIRM_CANCEL: clear buffer and hide modal. It could be even one value - buffer can be a modal flag (empty - hide, defined - show) dervied in mapStateToProps.
To be fully usable there should be an option to pass custom confirmation message along with reqConfirm.

Categories