typescript - 类型安全的 useDispatch 和 redux-thunk

标签 typescript redux redux-thunk

我正在使用 redux-thunk使用异步 Action 创建者。结果也返回给各自的调用者。

function fetchUserName(userId: number): Promise<string> {
  return Promise.resolve(`User ${userId}`)
}

function requestUserName(userId: number) {
  return (dispatch: Dispatch) => {
    return fetchUserName(userId).then(name => {
      dispatch({
        type: 'SET_USERNAME',
        payload: name,
      })
    })
  }
}

这样,存储被更新,同时允许组件直接处理响应。
function User() {
  const dispatch = useDispatch()
  useEffect(() => {
    dispatch(requestUserName(1))
      .then(name => {
        console.log(`user name is ${name}`)
      })
      .catch(reason => {
        alert('failed fetching user name')
      })
  }, [])
}

这按预期工作,但由于类型无效,TypeScript 不会对其进行编译。
  • dispatchuseDispatch 返回不被识别为返回 Promise 的函数,因此 TypeScript 认为 Property 'then' does not exist on type '(dispatch: Dispatch<AnyAction>) => Promise<void>'. .
  • 即使可以识别,Promise 也应该正确输入

  • 这种情况如何解决?

    我可以在 useDispatch 周围创建一个包装器。或重新定义 dispatch 的类型但我不知道这种类型在这种特殊情况下应该是什么样子。

    非常感谢您的任何建议。

    最佳答案

    useDispatch返回 Dispatch类型 used by Redux ,因此您只能使用它发送标准操作。要同时调度 thunk 操作,请将其类型声明为 ThunkDispatch (来自 redux-thunk)。ThunkDispatch接收存储状态的类型参数,extra thunk args和你的 Action 类型。它允许发送 ThunkAction ,这基本上是requestUserName的内部函数.
    例如,您可以这样键入:

    import { ThunkDispatch } from "redux-thunk";
    import { AnyAction } from "redux";
    
    type State = { a: string }; // your state type
    type AppDispatch = ThunkDispatch<State, any, AnyAction>; 
    // or restrict to specific actions instead of AnyAction
    
    function User() {
      const dispatch: AppDispatch = useDispatch();
      useEffect(() => {
        dispatch(requestUserName(1))
          .then(...)  // works now
      }, []);
      ...
    }
    
    AppDispatch也可以是inferred来自 typeof store.dispatch 的商店:
    import thunk, { ThunkDispatch, ThunkMiddleware } from "redux-thunk";
    
    const mw: ThunkMiddleware<State, AnyAction> = thunk;
    const dummyReducer = (s: State | undefined, a: AnyAction) => ({} as State);
    const store = createStore(dummyReducer, applyMiddleware(mw));
    
    type AppDispatch = typeof store.dispatch // <-- get the type from store
    
    TS Playground sample
    另请参阅 redux 关于使用带有钩子(Hook)的 typescript 的文档:https://redux.js.org/usage/usage-with-typescript#define-typed-hooks

    关于typescript - 类型安全的 useDispatch 和 redux-thunk,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59800913/

    相关文章:

    angular - Ionic 2 现在支持桌面。这是否意味着一个代码,所有设备?

    typescript - 为什么 <array>.[n] 类型与 <array>.at(n) 不同

    node.js - 如何修复react-scripts启动时的 “Error watching file for changes: ECONNRESET”错误?

    javascript - 完全获取数据后加载状态变化

    javascript - 如何?使用参数创建 Redux 选择器

    node.js - 错误断言 `args[3]->IsInt32()' 失败

    javascript - 使用 Angular 从弹出模式按钮删除时删除表中特定选定的行

    reactjs - 从同一组件内部调用时,React Router "Link to"不会加载新数据

    react-native - 使用 redux 时如何重新渲染 FlatList React Native

    Firebase 登录 promise 在我点击屏幕上的任意位置后才能解决