简体   繁体   English

我应该如何输入 React 的 dispatch function 才能执行像 Promise 这样的“then”方法

[英]How should I type React's dispatch function to be able to do a "then" method like a Promise

I have a simple app which dispatches an action on first load to populate the store.我有一个简单的应用程序,它在第一次加载时分派一个操作来填充商店。 I want to be able to run a then method on dispatch but typescript complains about this.我希望能够在dispatch时运行then方法,但 typescript 对此表示抱怨。

(According to redux's documentation, the return value of dispatching an action is the return value of the action itself ) (根据redux的文档,dispatch action的返回值是action本身的返回值)

Code available in Codesandbox代码在Codesandbox中可用

// app.jsx
function App() {
  const dispatch = useAppDispatch();

  useEffect(() => {
    dispatch(getTodos()).then((todos) => console.log(todos));
    //                   ^^^^^
    //                   Property 'then' does not exist on type '{ type: "GET_TODOS"; payload: Promise<AxiosResponse<Todo[], any>>; }'.
  }, []);
  return <div className="App">Hello World!</div>;
}

Store Configuration商店配置

I use @reduxjs/toolkit to configure my store and have a redux-promise-middleware set up for it so that upon "fulfillment" of my promised-based actions an <ACTION>_FULFILLED action will also be dispatched.我使用@reduxjs/toolkit来配置我的商店,并为其设置了一个redux-promise-middleware ,以便在“完成”我基于承诺的操作时,还将分派一个<ACTION>_FULFILLED操作。

// store.ts
import { configureStore } from '@reduxjs/toolkit';
import promiseMiddleware from 'redux-promise-middleware';
import rootReducer from './reducer';
import { useDispatch } from 'react-redux';

const store = configureStore({
    reducer: rootReducer,
    middleware: [promiseMiddleware],
});

export type RootState = ReturnType<typeof rootReducer>;
export type AppDispatch = typeof store.dispatch;

export const useAppDispatch = () => useDispatch<AppDispatch>();

export default store;

Reducer减速器

// reducer.ts
import produce, { Draft } from "immer";
import { Action } from "./action";

export type Todo = {
    userId: number;
    id: number;
    title: string;
    completed: boolean;
}

interface State {
  todos: Todo[];
}
const initialState: State = {
  todos: []
};

const reducer = produce((draft: Draft<State>, action: Action) => {
  switch (action.type) {
    case "GET_TODOS_FULFILLED": {
      const todos = action.payload.data;
      return todos;
    }
  }
}, initialState);

export default reducer;

Action行动

// action.ts
import axios from "axios";
import type { AxiosResponse } from "axios";
import type { Todo } from './reducer'

export const getTodos = (): {
  type: "GET_TODOS";
  payload: Promise<AxiosResponse<Todo[]>>;
} => ({
  type: "GET_TODOS",
  payload: axios.get("https://jsonplaceholder.typicode.com/todos")
});

export type Action = ReturnType<typeof getTodos>;

You can create a promise and then you can use.then like this.你可以创建一个 promise 然后你可以像这样使用.then。

import { useEffect } from "react";
import { getTodos } from "./action";
import { useAppDispatch } from "./store";

function App() {
  const dispatch = useAppDispatch();
  const myPromise = ()=>Promise.resolve(dispatch(getTodos())); /// creating promise 

  useEffect(() => {
    myPromise().then((res:any)=>{
      console.log(res.value.data)
    })
              
  }, []);
  return <div className="App">Hello World!</div>;
}

export default App;

Hope you are looking something like this.希望你看起来像这样。

dispatch would return whatever your action (thunk) returns. dispatch将返回您的操作 (thunk) 返回的任何内容。

It seems the part好像是部分

({
  type: "GET_TODOS",
  payload: axios.get("https://jsonplaceholder.typicode.com/todos")
})

might be wrong: what you wanted is probably可能是错的:你想要的可能是

const getTodos = (): ThunkAction => (dispatch) => 
  axios.get("https://jsonplaceholder.typicode.com/todos").then(todos => {
    dispatch({type: "GET_TODOS", payload: todos}); 
    return todos;
  });

This way you both have your action fired and your Promise returned from dispatch with todos payload.这样你们两个都可以触发你的动作,你的 Promise 从带有待办事项负载的调度中返回。

You may also want to type your ThunkAction with generics according to https://redux.js.org/usage/usage-with-typescript#type-checking-redux-thunks您可能还想根据https://redux.js.org/usage/usage-with-typescript#type-checking-redux-thunks 使用 generics 键入您的 ThunkAction

Ok I figured it out by myself.好的,我自己想出来了。 The problem was the incorrect typing of useAppDispatch .问题是useAppDispatch的输入不正确。

So in store.ts instead of having所以在store.ts而不是

export const useAppDispatch = () => useDispatch<AppDispatch>();

We should have我们本应该

import type { ThunkAction, ThunkDispatch } from "redux-thunk";
export type AppThunk<RT = void> = ThunkAction<
  Promise<RT>,
  RootState,
  unknown,
  AnyAction
>;
export type AppThunkDispatch = ThunkDispatch<RootState, void, Action>;
export const useAppDispatch = () => useDispatch<AppThunkDispatch>();

And then in action.ts we could write our thunk actions like this:然后在action.ts中我们可以这样写我们的thunk动作:

export const getTodos =
  (): AppThunk<{ type: "SET_TODOS"; payload: Todo[] }> => (dispatch) =>
    axios
      .get<Todo[]>("https://jsonplaceholder.typicode.com/todos")
      .then((response) => response.data)
      .then((todos) => dispatch(setTodos(todos)));

export const setTodos = (
  todos: Todo[]
): {
  type: "SET_TODOS";
  payload: Todo[];
} => ({
  type: "SET_TODOS",
  payload: todos
});

And lastly for using dispatch anywhere in our app:最后,在我们应用程序的任何地方使用 dispatch:

dispatch(getTodos()).then((todos) => console.log(todos));

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何在 ReactJS 中解决 promise 中的 useReducer 调度 function - How to resolve a useReducer's dispatch function inside a promise in ReactJS 我如何承诺在 React 中链式 redux / sagas 调度? - How can I promise chain a redux / sagas dispatch in React? 如何在我的反应组件上导入和使用 promise function? - how do i import and use promise function on my react component? 使用 React Hooks 时应该如何调度操作? - How Should I Dispatch Actions When Using React Hooks? 我如何从另一个不是反应组件的文件中调用 useReducer 调度 function? (不使用 Redux) - How do i call a useReducer dispatch function from another file, which is not a react component? (without using Redux) dispatch不是一个函数,如何在react中使用dispatch? - dispatch is not a function, how to use dispatch in react? React.Dispatch 时如何为 setState function 定义 TypeScript 类型<react.setstateaction<string> &gt; 不接受? </react.setstateaction<string> - How can I define TypeScript type for a setState function when React.Dispatch<React.SetStateAction<string>> not accepted? 如何通过 onClick function 在该上下文 onClick function 中创建在该上下文 onClick - How do I pass a React Context's state through an onClick function created in a method inside that context class? 如何在React Lifecycle Methods中正确调度动作? - How do I properly dispatch actions inside the React Lifecycle Methods? 如何使用 React Hooks 触发调度调用? - How do I trigger a call to dispatch using React Hooks?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM