首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >我应该如何输入React的调度函数才能像承诺那样做一个“然后”的方法

我应该如何输入React的调度函数才能像承诺那样做一个“然后”的方法
EN

Stack Overflow用户
提问于 2022-04-06 11:43:30
回答 3查看 1.5K关注 0票数 1

我有一个简单的应用程序,它在第一次加载时分派一个操作来填充商店。我希望能够在then上运行dispatch方法,但是类型记录会对此抱怨。

(根据redux的文档,发送操作的返回值是动作本身的返回值)

码箱中可用的代码

代码语言:javascript
复制
// 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>;
}

存储配置

我使用@reduxjs/toolkit配置我的存储,并为此设置了一个redux-promise-middleware,以便在“实现”基于承诺的操作时,<ACTION>_FULFILLED操作也将被分派。

代码语言:javascript
复制
// 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;

减速器

代码语言:javascript
复制
// 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;

动作

代码语言:javascript
复制
// 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>;
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2022-04-07 13:37:10

好吧,我自己想出来的。问题是useAppDispatch的类型不正确。

所以在store.ts中,而不是

代码语言:javascript
复制
export const useAppDispatch = () => useDispatch<AppDispatch>();

我们应该

代码语言:javascript
复制
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>();

然后在action.ts中,我们可以编写这样的thunk操作:

代码语言:javascript
复制
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
});

最后,对于在我们的应用程序中的任何地方使用调度:

代码语言:javascript
复制
dispatch(getTodos()).then((todos) => console.log(todos));
票数 0
EN

Stack Overflow用户

发布于 2022-04-06 13:33:54

您可以创建一个承诺,然后可以像这样使用.then。

代码语言:javascript
复制
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;

希望你长得像这样。

票数 0
EN

Stack Overflow用户

发布于 2022-04-06 13:46:57

dispatch将返回您的操作(thunk)返回的任何内容。

似乎这部分

代码语言:javascript
复制
({
  type: "GET_TODOS",
  payload: axios.get("https://jsonplaceholder.typicode.com/todos")
})

可能是错的:你想要的可能是

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

这样,你们两个的行动就会被触发,你们的承诺也会从待定任务的有效载荷中恢复过来。

您还可以根据ThunkAction的情况使用泛型键入https://redux.js.org/usage/usage-with-typescript#type-checking-redux-thunks

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71766161

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档