Here is my code:
//main.jsx with router
const router = createBrowserRouter([{
path: "/login",
element: <LoginPage/>,
errorElement: <ErrorPage/>,
action: loginAction
},
{
path: "*",
element: <h1>404 Page not found...</h1>,
},]);
ReactDOM.createRoot(document.getElementById('root')).render(
<React.StrictMode>
<Provider store={store}>
<RouterProvider router={router}/>
</Provider>
</React.StrictMode>,)
//LoginPage.jsx
function LoginPage() {
const navigation = useNavigation();
return (
<>
<main>
<LoginForm submitting={navigation.state === "submitting"}/>
</main>
</>
)
}
export default LoginPage;
export async function action({request}) {
//dispatch not possible
const formData = await request.formData();
const user = {
username: formData.get("username"),
password: formData.get("password")
}
try {
await login(user);
} catch (error){
return error
}
return redirect('/');
}
//LoginForm.jsx
function LoginForm({submitting}) {
return (
<>
<div className={classes.container}>
<Form method={"post"} action={'/login'} className={classes.form}>
<h1>Ocean 4 HEALTH</h1>
<fieldset>
<label htmlFor={"username"}>Username</label>
<input id={"username"} name={"username"} type={"text"} required={true} minLength={5} maxLength={30}/>
</fieldset>
<fieldset>
<label htmlFor={"password"}>Password</label>
<input id={"password"} name={"password"} type={"password"} required={true} minLength={8} maxLength={30}/>
</fieldset>
<button disabled={submitting}>
{submitting ? "Submitting ..." : "Login"}
</button>
</Form>
</div>
</>
)
}
//login.js
export async function login(user) {
//dispatch not possible
const response = await fetch(`${BASE_URL}/auth/login`, {
method: "POST",
body: JSON.stringify({
codF: user.username.toUpperCase(),
...user
}),
headers: {
"Content-Type": " application/json",
},
});
if (!response.ok) {
throw {message: "Ops, il login non è andato a buon fine", status: 500};
}
if (response.status === 226) {
throw {message: "Ops, hai già una sessione aperta su un pc o su un altro tab...", status: 226};
}
sessionStorage.setItem("token", JSON.stringify(user));
}
The problem/question:
How and where i can dispatch some action to send feedback to the user? I create a snackbar reducer for managing snackbar type, message and show (on, off) like this:
const snackbarSlice = createSlice({
name: 'snackbar',
initialState: {
show: false,
message: "",
type: ""
},
reducers: {
showSnackbar(state, action) {
state.show = true;
state.message = action.payload.message;
state.type = action.payload.type;
},
removeSnackbar(state) {
state.show = false;
}
}
})
export const snackbarActions = snackbarSlice.actions;
export default snackbarSlice
My goal is to dispatch showSnakbar if login succeed and an error message if there's an error.
Thanks in advance for the help. Any additional code or additional information I will be happy to give you
CodePudding user response:
You can do this by using the createAsynchThunk function provided in redux-toolkit
:
export const login = createAsyncThunk(
"user/login",
async (user, ext) => {
ext.dispatch(AnyActionYouWant1())
ext.dispatch(AnyActionYouWant2())
const response = await fetch(`${BASE_URL}/auth/login`, {
method: "POST",
body: JSON.stringify({
codF: user.username.toUpperCase(),
...user
}),
headers: {
"Content-Type": " application/json",
},
});
if (!response.ok) {
throw {message: "Ops, il login non è andato a buon fine", status: 500};
}
if (response.status === 226) {
throw {message: "Ops, hai già una sessione aperta su un pc o su un altro tab...", status: 226};
}
sessionStorage.setItem("token", JSON.stringify(user));
}
)
You will also need to add the login function in extraReducers
, you can do that by following this guide.
Another thing you need to keep in mind here is that login
is now an action, so it needs to be dispatched
to work.