使用react redux连接时,由于子组件上缺少道具,父组件上出现Typescript错误



App.tsx:类型"{}"在类型"IProps"中缺少以下属性:getProjects,projects

我遵循了这个例子(不确定它是否是最好的,但我很难找到一些使用react、redux、typescript和异步操作的好例子。有没有thunk,但人们推荐的似乎是thunk?我只是想知道为什么我会出现这个错误,并得到一些关于这是否是一个好方法的反馈。

我只是尝试实现一个单独的项目,我应该从api中获取一些项目。但是父组件抱怨没有向子组件发送道具?:S

App.tsx

import React from "react";
import logo from "./logo.svg";
import "./App.css";
import { Projects } from "./features/Projects";
function App() {
return (
<div className='App'>
<header className='App-header'>
<img src={logo} className='App-logo' alt='logo' />
<p>
Edit <code>src/App.tsx</code> and save to reload.
</p>
<a
className='App-link'
href='https://reactjs.org'
target='_blank'
rel='noopener noreferrer'
>
Learn React
</a>
<Projects />
</header>
</div>
);
}
export default App;

还原剂.ts

import { IProjectState, ProjectActions } from "./types";
import { Reducer } from "react";
const initialProjectState: IProjectState = {
projects: [],
};
export const projectReducer: Reducer<IProjectState, ProjectActions> = (
state = initialProjectState,
action: ProjectActions
): IProjectState => {
switch (action.type) {
case "GettingProjects": {
return {
...state,
};
}
case "GotProjects": {
return {
...state,
projects: action.projects,
};
}
}
};

actions.ts

import { IProject, IGotProjectsAction, IGettingProjectsAction } from "./types";
import agent from "../../agent";
import { ThunkAction } from "redux-thunk";
import { ActionCreator, Dispatch } from "redux";
export const getProjectsActionCreator: ActionCreator<ThunkAction<
// The type of the last action to be dispatched - will always be promise<T> for async actions
Promise<IGotProjectsAction>,
// The type for the data within the last action
IProject[],
// The type of the parameter for the nested function
null,
// The type of the last action to be dispatched
IGotProjectsAction
>> = () => {
return async (dispatch: Dispatch) => {
const gettingProjectsAction: IGettingProjectsAction = {
type: "GettingProjects",
};
dispatch(gettingProjectsAction);
const projects = await agent.Projects.list();
const gotProjectsAction: IGotProjectsAction = {
projects,
type: "GotProjects",
};
return dispatch(gotProjectsAction);
};
};

types.ts

import { Action } from "redux";
export interface IProject {
id: string;
name: string;
number: string;
status: number;
description: string;
}
export interface IProjectState {
projects: IProject[];
}
export interface IGettingProjectsAction extends Action<"GettingProjects"> {}
export interface IGotProjectsAction extends Action<"GotProjects"> {
projects: IProject[];
}
export type ProjectActions = IGettingProjectsAction | IGotProjectsAction;

Projects.tsx

import React, { FC, useEffect } from "react";
// import { IProjectState } from "../store/project/types";
import { connect } from "react-redux";
import { IAppState } from "../store";
import { getProjectsActionCreator } from "../store/project/actions";
import { IGotProjectsAction, IProject } from "../store/project/types";
import { ThunkDispatch } from "redux-thunk";
import { AnyAction } from "redux";
interface IProps {
getProjects: () => Promise<IGotProjectsAction>;
projects: IProject[];
}
export const Projects: FC<IProps> = ({ getProjects, projects }) => {
useEffect(() => {
getProjects();
}, []);
return <div></div>;
};
const mapStateToProps = (store: IAppState) => {
return {
projects: store.project.projects,
};
};
const mapDispatchToProps = (dispatch: ThunkDispatch<any, any, AnyAction>) => {
return {
getProjects: () => dispatch(getProjectsActionCreator()),
};
};
export default connect(mapStateToProps, mapDispatchToProps)(Projects);

store/index.ts

import { projectReducer } from "./project/reducers";
import { combineReducers, createStore, applyMiddleware, Store } from "redux";
import thunk from "redux-thunk";
import { IProject } from "./project/types";
const rootReducer = combineReducers({
project: projectReducer,
});
interface IProjectState {
readonly projects: IProject[];
}
export interface IAppState {
project: IProjectState;
}
export function configureStore(): Store<IAppState> {
const store = createStore(rootReducer, undefined, applyMiddleware(thunk));
return store;
}

代理人.ts

import axios, { AxiosResponse } from "axios";
import { IProject } from "./store/project/types";
axios.defaults.baseURL = "http://localhost:5000/api";
const responseBody = (response: AxiosResponse) => response.data;
const requests = {
get: (url: string) => axios.get(url).then(responseBody),
post: (url: string, body: {}) => axios.post(url, body).then(responseBody),
put: (url: string, body: {}) => axios.put(url, body).then(responseBody),
delete: (url: string) => axios.delete(url).then(responseBody),
};
const Projects = {
list: () => axios.get(`/projects`).then(responseBody),
create: (project: IProject) => requests.post("/projects", project),
};
export default {
Projects,
};
import { Projects } from "./features/Projects";

您正在导入命名导出。这就是用这行定义的组件:

export const Projects: FC<IProps> = ({ getProjects, projects }) => {
// etc

这是而不是用此行定义的组件:

export default connect(mapStateToProps, mapDispatchToProps)(Projects);

由于您正在导入未连接的组件,您需要自己提供所有的道具,但您没有,所以typescript抱怨您没有给它正确的道具。

最有可能的是,修复方法是通过将导入更改为来导入连接的组件

import Projects from "./features/Projects";

在我的项目中,我通常根本不导出未连接的组件。它不打算直接使用,所以导出它唯一能做的就是让这样的错误成为可能。

最新更新