Правильный тип асинхронного действия в redux с промежуточным программным обеспечением redux-thunk

#reactjs #typescript #react-redux #redux-thunk

Вопрос:

Я создал простое приложение react во время изучения промежуточного программного обеспечения redux-thunk. У меня проблема с транспиляцией из-за неправильного типа асинхронного действия fetchPosts в интерфейсе PostListProps.

Ниже я показываю весь код функционального компонента, в котором заключается проблема:

 import React, { useEffect } from 'react'
import { connect } from 'react-redux'
import { fetchPosts } from '../actions'
import Action from '../actions/actionTypes'
import { Dispatch } from "react";
import State from '../reducers/State'

interface PostListProps { 
    fetchPosts: () => (dispatch: Dispatch<Action>) => Promise<void>
}

const PostList = (props: PostListProps) => {
    useEffect(() => {
        props.fetchPosts()
    }, [])
    return (
        <div>Post List</div>
    )
}

const mapStateToProps = (state: State) => {
    return { posts: state.posts };
};

export default connect(
    mapStateToProps,
    { fetchPosts }
)(PostList);
 

Мой код переносится без ошибок только тогда, когда я изменяю тип функции fetchPosts на:

fetchPosts: () => any

Ниже я представляю код функции fetchPosts:

 import Action, { ActionType } from "./actionTypes";
import jsonPlaceholder from "../apis/jsonPlaceholder";
import { Dispatch } from "react";
import Post from '../apis/Post'
import State from "../reducers/State";
import { AxiosResponse } from "axios";

export const fetchPosts = () => {
    return async (dispatch: Dispatch<Action>) => {
        const response: AxiosResponse<Post[]> = await jsonPlaceholder.get<Post[]>('/posts')
        dispatch({type: ActionType.FETCH_POSTS, payload: response.data });
    }
}
 

Ошибка выглядит так, как показано ниже:
введите описание изображения здесь

Я понятия не имею, где может быть проблема? Почему мой тип fetchPosts() неправильный? Я хотел бы это выяснить. Я был бы благодарен за помощь.

Ответ №1:

Ваш компонент не связан с деталями того, как сообщения извлекаются и отправляются в магазин, поэтому этот dispatch бит не нужно отражать в интерфейсе. Вся необходимая проводка обрабатывается react-redux .

Попробуйте это:

 interface PostListProps {
    fetchPosts: () => void;
}
 

Обратите внимание, что Promise это не упоминается в интерфейсе, так как ваш компонент все равно его не ожидает.

Что касается того, как правильно ввести dispatch функцию, мы могли бы вывести правильный тип из store экземпляра:

 import thunk, { ThunkMiddleware } from 'redux-thunk';

interface AppState {
    posts: PostsState;
    claims: ClaimsState;
}

type AppAction = PostsAction | ClaimsAction;

type AppThunk = ThunkMiddleware<AppState, AppAction>;

const reducer: Reducer<AppState, AppAction> = combineReducers({
  posts: postsReducer,
  claims: claimsReducer,
});

const store = createStore(
    reducer,
    applyMiddleware(thunk as AppThunk)
);

// the type is inferred as
// Dispatch<AppAction> amp; ThunkDispatch<AppState, undefined, AppAction>
type AppDispatch = typeof store.dispatch;
 

Состояния и типы действий, зависящие от среза, будут определены в соответствующих срезах, что-то вроде этого:

 // posts slice
export type PostsState = Post[];
export type PostsAction =
    | FetchPostsAction
    | FetchPostsFulfilledAction
    | FetchPostsRejectedAction;

// claims slice
export type ClaimsState = Claim[];
export type ClaimsAction =
    | CreateClaimsAction;
 

Возможно, вы также захотите взглянуть на пакет redux-toolkit, где о многом из этого уже позаботились.

Комментарии:

1. Спасибо, это работает, но у меня есть еще одна проблема. Я не вижу сообщений. Они не определены внутри моего посткомпонента. Вот мое репо: github.com/pirx1988/redux-thunk-posts

2. Вам следует проверить свой combineReducers() звонок. Это должно быть combineReducers({ posts: postReducer }) скорее, чем просто combineReducers({ postReducer }) . Последнее создает неправильную форму состояния, { postReducer: [] } .