首页 > 解决方案 > 如何在 useReduce 挂钩中发出异步服务器请求?

问题描述

我已经使用 useContext 设置了一个 useReducer 挂钩来接收用于登录的电子邮件和密码,我已经创建了一个组件来从服务器获取身份验证令牌。我目前无法弄清楚如何使用返回的 accessToken 更新减速器。

减速器

    export const loginInitialState = {
      isLogin: false,
      accessToken: '',
    } as LoginInitialState
    
//this is the part that is not working
    export const loginReducer = async (
      state: LoginInitialState,
      { actionType, email, password }: LoginPayload
    ) => {
      switch (actionType) {
        case 'login':
          const data = await loginRequest(email, password)
          console.log(data)
          return {
            ...data,
          }
        case 'logout':
          return {
            ...loginInitialState,
          }
      }
    }

使用上下文

export const LoginStateContext = createContext<LoginStateContextProps>(false)
export const LoginDispatchContext = createContext<LoginDispatchContextProps>(
  () => {}
)
export const AccessTokenContext = createContext<AccessTokenProps>('')

export const LoginProvider = ({
  children,
}: React.PropsWithChildren<unknown>) => {
  //@ts-ignore
  const [isLogin, dispatchLogin] = useReducer(loginReducer, loginInitialState)

  return (
    <AccessTokenContext.Provider value={isLogin.accessToken}>
      <LoginDispatchContext.Provider value={dispatchLogin}>
        <LoginStateContext.Provider value={isLogin.isLogin}>
          {children}
        </LoginStateContext.Provider>
      </LoginDispatchContext.Provider>
    </AccessTokenContext.Provider>
  )
}

获取请求

export const loginRequest = async (email?: string, password?: string) => {
  let data: any
  await axios
    .post(`blah blah blah`, {
      emailAddress: email,
      password: password,
    })
    .then((res) => {
      data = res.data
    })
  if (data) {
    return {
      isLogin: true,
      accessToken: data.accessToken,
    }
  } else {
    return { ...loginInitialState }
  }
}

调度点

const onLoginClick = () => {
    dispatchLogin({ actionType: 'login', email: email, password: password })
  }

我可以控制台记录返回的身份验证密钥,但我无法让我的减速器更新到返回的状态。

标签: javascriptreactjsreact-hooksuse-contextuse-reducer

解决方案


在 a 中执行异步操作useReducer是不可能的。如果我没记错的话,你的状态变成了一个承诺。

您必须做的是在外部执行该操作并通过调度传递数据。所以,你的 reducer 只处理数据。

此外,通过在外部抽象您的逻辑,您可能会对单元测试感兴趣,因此可以模拟不同场景的响应。如果它不适用,也许你想保持你的 API 隔离,不知道,每个应用程序/团队/开发人员都有自己的用例。

最后一点,如果你使用async/await不要使用then. 它是一个或另一个。


推荐阅读