使用React Redux Connect时,父组件上的打字稿错误导致子组件上缺少道具

时间:2020-05-03 23:40:24

标签: typescript asynchronous redux react-redux axios

App.tsx:类型“ {}”缺少类型“ IProps”中的以下属性:getProjects,项目

我遵循了this的示例(不确定是否是最好的示例,但是我很难找到一些使用react,redux,typescript和async操作的好示例。是人们推荐的东西吗?我想知道为什么会收到此错误,以及一些有关此方法是否正确的反馈。

我刚刚尝试实现一个项目,我应该从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;

reducers.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;
}

agent.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,
};

1 个答案:

答案 0 :(得分:1)

import { Projects } from "./features/Projects";

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

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

这不是不是与此行定义的组件:

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

由于要导入未连接的组件,因此您需要自己提供所有道具,但实际上并非如此,因此打字稿抱怨您没有为其提供正确的道具。

最有可能的解决方法是,通过将导入更改为以下内容来导入连接的组件:

import Projects from "./features/Projects";

在我的项目中,我通常根本不导出未连接的组件 。不能直接使用它,因此导出它的唯一作用就是使这种错误成为可能。