I provide operations with Redux toolkit and formik.
I tried createAsyncThunk and normally but the value comes up empty every time.
store.ts
import { configureStore } from '@reduxjs/toolkit'
import auth from './auth'
import err from './errors'
import loading from './loading'
export const store = configureStore({
reducer: {
auth,
err,
loading
},
})
export type RootState = ReturnType<typeof store.getState>
export type AppDispatch = typeof store.dispatch
login.ts
export function Login() {
const dispatch = useAppDispatch();
const {fieldErrors} = useAppSelector(state => state.err);
const {isLoading} = useAppSelector(state => state.loading);
const formik = useFormik({
initialValues,
enableReinitialize: true,
validationSchema: loginSchema,
onSubmit: (values, {setStatus, setSubmitting, setFieldError}) => {
dispatch(loginRequest(values)).then((res) => {
console.log('then')
console.log({res});
console.log({fieldErrors});
})
/*dispatch(loginRequest(values))
.then(res => {
console.log('then')
console.log({res});
console.log({fieldErrors});
setStatus(fieldErrors.flatMap(item => item.error).join("\n"));
})
.catch(res => {
console.log('catch')
console.log({res});
console.log({fieldErrors});
setStatus(fieldErrors.flatMap(item => item.error).join("\n"));
});*/
/*AuthService.login("ahmet", "mehmet")
.then((res) => {
console.log(res);
console.log('success');
}).catch(() => {
console.log({fieldErrors});
//setStatus(fieldErrors.flatMap(item => item.error).join("\n"));
setSubmitting(false);
})*/
},
})
return (
<>
....
</>
)
}
request.ts
import { store } from "../store";
import { removeAllFieldError, setErrors } from "../store/errors";
import { hideLoading, showLoading } from "../store/loading";
const API_URL: any = process.env.REACT_APP_API_ENDPOINT;
const parseData = (data: object | boolean | undefined) => {
let formData = new FormData();
if(typeof data === "object"){
for(let [key, val] of Object.entries(data)){
formData.append(key, val);
}
}
return formData;
}
const getAPIAbsoluteUrl = (path:string) => {
if(process.env.NODE_ENV === "development")
return `/api${path}`
return `${API_URL}${path}`
}
const request = (
url: RequestInfo | URL | any,
data: object | boolean | undefined = false,
method = "GET",
formType = "FORM_DATA"
) => {
return new Promise(async (resolve, reject) => {
await fetch('/sanctum/csrf-cookie', {method: "GET"});
store.dispatch(showLoading())
store.dispatch(removeAllFieldError())
const options: RequestInit = {
method,
credentials: 'include'
};
if(data && method === "POST"){
options.body = formType === "JSON" ? JSON.stringify(data) : parseData(data);
}
const response = await fetch(url, options);
let result: any = response;
if(response.headers.get("Content-Type") === "application/json")
result = await response.json()
store.dispatch(hideLoading())
if(response.ok){
resolve(result);
}else{
if(response.status === 422)
store.dispatch(setErrors(result.errors));
reject(result);
}
});
}
export const postRequest = (url: any, data: object | boolean | undefined) => request(getAPIAbsoluteUrl(url), data, "POST")
export const getRequest = (url: any) => request(url)
export const putRequest = (url: any, data: object | boolean | undefined) => request(getAPIAbsoluteUrl(url), data, "PUT")
export const deleteRequest = (url: any) => request(getAPIAbsoluteUrl(url), false, "DELETE")
export const postJSONRequest = async (url: any, data: object | boolean | undefined) => request(getAPIAbsoluteUrl(url), data, "POST", "JSON")
export const getJSONRequest = (url: any) => request(getAPIAbsoluteUrl(url), false, "GET", "JSON")
export const putJSONRequest = (url: any, data: object | boolean | undefined) => request(getAPIAbsoluteUrl(url), data, "PUT", "JSON")
export const deleteJSONRequest = (url: any) => request(getAPIAbsoluteUrl(url), false, "DELETE", "JSON")
errors.ts
import { createSlice } from "@reduxjs/toolkit";
export interface IErrorState {
fields: Array<String>,
errors: Array<unknown|string>,
fieldErrors: Array<IFieldErrorState>,
}
export interface IFieldErrorState {
key: string,
error: string,
}
const initialState : IErrorState = {
fields: [],
errors: [],
fieldErrors: []
}
export const errorsSlice = createSlice({
'name': 'errors',
initialState,
reducers: {
setErrors: (state, action) => {
const fields = Object.keys(action.payload)
const errors = Object.values(action.payload).flat()
const fieldErrors: Array<IFieldErrorState> = []
fields.forEach(element => {
fieldErrors.push({
key: element,
error: action.payload[element][0]
});
});
return {
...state,
errors,
fieldErrors,
fields
}
},
removeError: (state, action) => {
state.errors.splice(action.payload.index, 1);
},
removeAllFieldError: (state) => {
state.fieldErrors = []
}
}
})
export const { setErrors, removeError, removeAllFieldError } = errorsSlice.actions
export default errorsSlice.reducer
auth.ts
import { createAsyncThunk, createSlice } from "@reduxjs/toolkit";
import { AuthService } from "../services";
export interface ILoginField{
email: string,
password: string
}
export const loginRequest = createAsyncThunk("auth/loginRequest", async (payload: ILoginField) => {
await AuthService.login(payload.email, payload.password)
});
export interface AuthState {
user: Object | null
}
const initialState : AuthState = {
user: null
}
export const authSlice = createSlice({
'name': 'auth',
initialState,
reducers: {
}
})
export default authSlice.reducer
authService.ts
import { postJSONRequest } from "../request";
export const login = (
email: string,
password : string
) => postJSONRequest("/v1/auth/login", {email, password})
Finally, the fieldErrors variable in login.ts returns empty. But when I console.log in errors.ts or request.ts, the value is full.
Redux dev tool screenshot;
When I press the button for the second time, the value comes full.
I don't understand where is the problem or what am I doing wrong. Thank you.