M
M
Mashush2022-04-05 06:32:44
JSON Web Token
Mashush, 2022-04-05 06:32:44

How to remove request duplication in useEffect?

There is such a reducer for the user:

const defaultState = {
    user: {},
    auth: false
}

const SET_USER = 'SET_USER'
const SET_AUTH = 'SET_AUTH'

function userReducer(state = defaultState, action) {
    switch(action.type) {
        case SET_USER: return {...state, user: action.payload}
        case SET_AUTH: return {...state, auth: action.payload}
        default: return state
    }
}

export function SET_USER_ACTION(payload) {
    return {type: SET_USER, payload}
}

export function SET_AUTH_ACTION(payload) {
    return {type: SET_AUTH, payload}
}

export default userReducer


And such a hook for convenient work with it:

import axios                               from 'axios'
import {useDispatch, useSelector}          from 'react-redux'
import { SET_USER_ACTION, SET_AUTH_ACTION} from '../store/reducers/user.reducer'
import UserService                         from '../services/user.service'
import {API_URL}                           from '../utils/axios'

function useUser() {
    const dispatch     = useDispatch()
    const {user, auth} = useSelector((state) => state.userData)

    async function signUp(email, password) {
        try {
            const response = await UserService.SignUp(email, password)
            localStorage.setItem('accessToken', response.data.tokens.accessToken)
            dispatch(SET_USER_ACTION(response.data.person))
            dispatch(SET_AUTH_ACTION(true))
        } catch (error) {
            console.log(error.response.data.message)
        }
    }

    async function signIn(email, password) {
        try {
            const response = await UserService.SignIn(email, password)
            localStorage.setItem('accessToken', response.data.tokens.accessToken)
            dispatch(SET_USER_ACTION(response.data.person))
            dispatch(SET_AUTH_ACTION(true))
        } catch (error) {
            console.log(error.response.data.message)
        }
    }

    async function signOut() {
        try {
            await UserService.SignOut()
            localStorage.removeItem('accessToken')
            dispatch(SET_USER_ACTION({}))
            dispatch(SET_AUTH_ACTION(false))
        } catch (error) {
            console.log(error.response.data.message)
        }
    }

    async function checkAuth() {
        try {
            const response = await axios.get('/api/common/persons/refresh', {withCredentials: true, baseURL: API_URL})
            localStorage.setItem('accessToken', response.data.tokens.accessToken)
            dispatch(SET_USER_ACTION(response.data.person))
            dispatch(SET_AUTH_ACTION(true))
        } catch (error) {
            console.log(error.response.data.message)
        }
    }

    return {user, auth, signUp, signIn, signOut, checkAuth}
}

export default useUser


All that UserService does in this case is send requests using axios to my api. And here is what exactly happens in the root App:

import {useEffect, useState} from 'react'
import useUser                     from './hooks/use.user'

function App(props) {

    const [email, setEmail]                                                 = useState('')
    const [password, setPassword]                                     = useState('')
    const {auth, user, signUp, signIn, signOut, checkAuth} = useUser()

    function submitSignUp() {
        signUp(email, password)
    }

    function submitSignIn() {
        signIn(email, password)
    }

    function submitSignOut() {
        signOut()
    }

    useEffect(() => {
        if (localStorage.getItem('accessToken')) {
            checkAuth()
        }
    }, [])

    if (auth) {
        return (
            <div>
                <h1>Добро пожаловать, {user.email}!</h1>
                <button type="button" onClick={submitSignOut}>Выйти</button>
            </div>
        )
    }

    return (
        <form className="form">
            <input name="email"    type="email"    value={email}    onChange={(e) => setEmail(e.target.value)} />
            <input name="password" type="password" value={password} onChange={(e) => setPassword(e.target.value)} />
            <div className="row">
                <button type="button" onClick={submitSignIn}>Вход</button>
                <button type="button" onClick={submitSignUp}>Регистрация</button>
            </div>
        </form>
    )

}

export default App


But here's what I see in the requests in this case:

gYDqx831UQM.jpg?size=749x253&quality=96&sign=f0e6bfd41fc56c450785384b6c56d662&type=album

cJ_lgXNn8S4.jpg?size=749x248&quality=96&sign=5faeddab66ef819b4e1b317d556596f6&type=album

There are two of them sent. Moreover, the first one works as it should and on the server in the logs it also works correctly. But new cookies do not have time to be installed, because a new request is sent with old cookies, which is processed incorrectly.

That is, all that worries me - brothers, how to remove the second request?)

Answer the question

In order to leave comments, you need to log in

1 answer(s)
A
Alexandroppolus, 2022-04-05
@Mashush

if there is React.StrictMode somewhere, delete the fuck.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question