#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: [] }
.