I have an asynchronous Thunk:
export const loginThunk = createAsyncThunk(
"user/login",
async ({ login, password }: { login: string; password: string }) => {
const { token } = await authService.login(login, password);
return token;
}
);
Using it in store:
extraReducers: (builder) => {
builder
.addCase(loginThunk.fulfilled, (state, action) => {
state.token = action.payload;
state.isLoading = false;
state.error = false;
})
.addCase(loginThunk.pending, (state) => {
state.isLoading = true;
state.error = false;
})
.addCase(loginThunk.rejected, (state, action) => {
state.isLoading = false;
state.error = true;
})
Target component:
const Auth = () => {
const dispatch = useAppDispatch();
const { token, error } = useAppSelector((state) => state.auth);
const [login, setLogin] = useState("");
const [password, setPassword] = useState("");
const navigate = useNavigate();
const onSubmitHandle = async (e: FormEvent) => {
e.preventDefault();
if (login !== "" && password !== "") {
await dispatch(loginThunk({ login: login, password: password }));
!error && token !== null ? navigate("/editor") : null;
}
};
return (
<div className="login">
<form className="login__form" onSubmit={onSubmitHandle}>
<h2 className="login__title">Editor</h2>
<label className="login-form__label">
Login
<input
type="text"
name="login"
onChange={(e) => setLogin(e.target.value)}
/>
</label>
<label className="login-form__label">
Пароль
<input
type="text"
name="password"
onChange={(e) => setPassword(e.target.value)}
/>
</label>
<button type="submit" className="login__button">
Enter
</button>
{error ? "Error, try do it later" : null}
</form>
</div>
);
};
After click "Enter" I get token and put it to store. In Redux-Devtools I see that token is in store, but component doesn’t update. Interesting, but component updating, if I change field error, but token no.
2
Answers
You are accessing the token only in your ‘onSubmitHandle()’. Only there you check for the token and not when the component rerender.
Add ‘useEffect’ and check there for the token, and make the navigation in the useEffect.
The Auth component rerenders, but the navigation change doesn’t executes.
createAsyncThunks
always resolve. If you are wanting to use the returnedtoken
value then you need to do two things.unwrap
the resolved result. See Handling Think Results for more details.token
value instead of referencing the stale closure over the selectedtoken
value from the outer scope.Example: