0

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;

redux dev tool image

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.

Orgenus
  • 1
  • 2

0 Answers0