React useReducer не обновляет состояние

Я использую useReducer для обновления errorsState, когда пользователь вошел в систему и потерпел неудачу. Я читал много решений, и было сказано, что dispatch является асинхронным, и я знаю это, поэтому я поместил console.log в useEffect, чтобы увидеть изменение errorsState, но, к сожалению, это не изменилось. Вот мой код

Login.jsx

export default function Login({ userProps }) {
  //
  // some variables and state
  //
  const { loading, user } = useLogin({ email: state.email }, state.submitted)
  const [errors, dispatch] = useReducer(errorsReducer, errorsState)

  useEffect(() => {
    console.log("errors", errors) // it won't triggered because errors state didn't updating from UseLogin
  }, [errors])

  return content
}

Вот функция выборки useLogin

AuthAction.js

export const useLogin = (data, submitted) => {
  const [state, dispatch] = useReducer(userReducer, userState)
  const [errors, errorsDispatch] = useReducer(errorsReducer, errorsState)

  useEffect(() => {
    if (!submitted) return

    dispatch({
      type: USER_ACTIONS.MAKE_REQUEST,
    })

    ticketApi.login(data).then(({ res, status }) => {
      if (status !== "failed") {
        // Save to local storage
        const { token } = res
        // set token to local storage
        localStorage.setItem("jwtToken", token)
        // Set token to Auth Header
        setAuthToken(token)
        // decode token to get user data with jwt-decode
        const decoded = jwt_decode(token)
        // set current user
        return dispatch({
          type: USER_ACTIONS.GET_USER,
          payload: decoded,
        })
      }

      dispatch({
        type: USER_ACTIONS.END_REQUEST,
      })

      return errorsDispatch({
        type: ERRORS_ACTIONS.GET_ERRORS,
        payload: res.response.data,
      })
    })
  }, [submitted])

  return state
}

Я попытался вставить console.log в ERRORS_ACTIONS.GET_ERRORS, чтобы увидеть ответ, и все прошло нормально. Так где я ошибся?


person panji gemilang    schedule 02.10.2020    source источник
comment
Я думаю, вы можете вызывать useReducer при двух разных состояниях ошибки. Диспетчерские действия на одном, осмотр другого.   -  person Mark Swardstrom    schedule 02.10.2020
comment
Я думаю, это был правильный ответ. потому что нет другой переменной errors, кроме errorsReducer   -  person panji gemilang    schedule 02.10.2020
comment
Я знаю, это звучит глупо, но ... ваш пользовательский хук пишется с заглавной буквы, он должен начинаться с нижнего регистра use, попробуйте изменить это   -  person diedu    schedule 02.10.2020
comment
ничего не меняется, все равно не работает   -  person panji gemilang    schedule 02.10.2020
comment
откуда errorsState?   -  person diedu    schedule 02.10.2020


Ответы (1)


useReducer позволяет вам лучше управлять сложными состояниями, это не контейнер состояний, вы создаете 2 разных состояния, одно внутри useLogin, а другое в вашем Login компоненте, возвращайте errors из вашего useLogin хука, чтобы компонент входа мог видеть это.

Авторизоваться

export default function Login({ userProps }) {
  //
  // some variables and state
  //
  const { loading, user, errors } = useLogin({ email: state.email }, state.submitted)

  useEffect(() => {
    console.log("errors", errors)
  }, [errors])

  return content
}

useLogin

export const useLogin = (data, submitted) => {
  const [state, dispatch] = useReducer(userReducer, userState)
  const [errors, errorsDispatch] = useReducer(errorsReducer, errorsState)

  useEffect(() => {
    if (!submitted) return

    dispatch({
      type: USER_ACTIONS.MAKE_REQUEST,
    })

    ticketApi.login(data).then(({ res, status }) => {
      if (status !== "failed") {
        // Save to local storage
        const { token } = res
        // set token to local storage
        localStorage.setItem("jwtToken", token)
        // Set token to Auth Header
        setAuthToken(token)
        // decode token to get user data with jwt-decode
        const decoded = jwt_decode(token)
        // set current user
        return dispatch({
          type: USER_ACTIONS.GET_USER,
          payload: decoded,
        })
      }

      dispatch({
        type: USER_ACTIONS.END_REQUEST,
      })

      return errorsDispatch({
        type: ERRORS_ACTIONS.GET_ERRORS,
        payload: res.response.data,
      })
    })
  }, [submitted])

  return { ...state, errors };
}
person diedu    schedule 02.10.2020
comment
да, в этом есть смысл. Я думал, что useReducer будет работать так же, как redux. Большое спасибо, но я уже перешел на redux - person panji gemilang; 02.10.2020