Реагировать с ошибкой TypeScript при использовании соединения Redux-Thunk. «Типы параметров props и props несовместимы». - PullRequest
1 голос
/ 26 мая 2020

Я пытаюсь заставить Redux-Thunk работать в приложении TypeScript React. К сожалению, я столкнулся с этой ошибкой и исчерпал все ресурсы, которые мог найти, пытаясь найти ответ на эту ошибку.

Я искренне застрял и надеюсь, что кто-то может помочь.

Ошибка :

Argument of type 'typeof App' is not assignable to parameter of type 'ComponentType<Matching<{ todos: TodoItem[]; loading: boolean; } & typeof import("C:/Users/cevan/Documents/reactFinalShow/frontend-app/src/store/actions"), ClassAttributes<App> & IAppProps & DispatchProps>>'.
  Type 'typeof App' is not assignable to type 'ComponentClass<Matching<{ todos: TodoItem[]; loading: boolean; } & typeof import("C:/Users/cevan/Documents/reactFinalShow/frontend-app/src/store/actions"), ClassAttributes<App> & IAppProps & DispatchProps>, any>'.
    Types of parameters 'props' and 'props' are incompatible.
      Type 'Matching<{ todos: TodoItem[]; loading: boolean; } & typeof import("C:/Users/cevan/Documents/reactFinalShow/frontend-app/src/store/actions"), ClassAttributes<App> & IAppProps & DispatchProps>' is not assignable to type 'Readonly<Props>'.
        The types returned by 'getTodoItems()' are incompatible between these types.
          Type '(dispatch: Dispatch<AnyAction>) => Promise<string | void | TodoItem[]>' is missing the following properties from type 'TodoItem[]': pop, push, concat, join, and 27
more.  TS2345

Мой код

App.tsx


import React, { Component } from 'react'
import { connect } from 'react-redux';
import * as TodoItemActions from './store/actions'
import { RootState } from './store';
import { ThunkDispatch } from 'redux-thunk';
import { AnyAction, Dispatch, bindActionCreators } from 'redux';
import { GotTodoItems } from './store/types';
import { TodoItem } from './models/TodoItem';

export interface IAppProps {
  todos: TodoItem[];
  loading: boolean;
}

type Props = IAppProps & DispatchProps;

export class App extends React.Component<Props> {
  public render() {
    let { getTodoItems } = this.props;
    let idk = getTodoItems();
    console.log(idk);
    return (
      <div>

      </div>
    );
  }
}


const mapStateToProps = (state: RootState) => {
  console.log(state);
  return {
    todos: state.todoReducer.todoItems,
    loading: state.todoReducer.loading
  };
}

const mapDispatchToProps = (dispatch: Dispatch) => bindActionCreators(TodoItemActions, dispatch);

interface DispatchProps {
  getTodoItems: () => TodoItem[];
}

export default connect(
  mapStateToProps, //bring in the mapStateToProps function to inform redux of what you want to bring in and how to bring it in (to props)
  mapDispatchToProps
  //bring in specific actions into this component
)(App);

actions.ts (из моего магазина)

import { TodoActionTypes, GETTING_TODO_ITEMS, GOT_TODO_ITEMS } from "./types";
import { TodoItem } from "../models/TodoItem";
import agent from "../api/agent";

import { Dispatch } from 'redux';
import { AppActions } from "../models/actions";

import { store } from '../index';

const requestTodoItems = (): AppActions => {
    return {
        type: GETTING_TODO_ITEMS,
        todoItems: []
    }
}

export function getTodoItems() {
    return (dispatch: Dispatch) => {
        dispatch(requestTodoItems());

        let errorEncountered = false;

        let hasErrored = false;

        let response = agent.ToDoApis.getList(new URLSearchParams);
        return response.then(
            value => {
                //success
                console.log(value)
                return value;
            },
            reason => {
                //rejection
                console.log(reason)
            }
        ).catch(error => `Error when fetching to do items ${error}`)
    }
}



        // agent.ToDoApis.getList
        //     .(
        //         (response) => response.json(),
        //         (error) => {
        //             hasErrored = true;
        //             console.log(error);
        //             dispatch(requestTodoItems());
        //         }
        //     )
        //     .then((json) => {
        //         if (!hasErrored) {
        //             dispatch(returnTodoItems(json));
        //         }
        //     });

        // return agent.ToDoApis.getList(new URLSearchParams)
        // .then(
        //     (response) => response.IsDone,
        //     (error) => {
        //         errorEncountered = true;
        //         console.log(error);
        //         dispatch(requestTodoItems());
        //     }
        // )
        // .then((json) => {
        //     if(!errorEncountered){
        //         dispatch(returnTodoItems(json))
        //     }
        // })

// export async function getTodoItems(isDone: boolean): Promise<TodoActionTypes> {
//     console.log("ABOVE");
//     const response = await agent.ToDoApis.getList;
//     console.log("ABOVE");
//     console.log(response);
//     console.log("ABOVE");
//     dispatch({
//         type: GET_TODO_ITEMS,
//         isDone: isDone
//     });
// }

// export function createNewTodo(todoItem: TodoItem): TodoActionTypes {
//     return {
//         type: CREATE_NEW_TODO,
//         todoItem: todoItem
//     }
// }

// export function toggleDoneStatusForTodo(id: string): TodoActionTypes {
//     return {
//         type: TOGGLE_DONE_STATUS_FOR_TODO,
//         id: id
//     }
// }

// export function updateEntireTodo(todoItem: TodoItem): TodoActionTypes {
//     return {
//         type: UPDATE_ENTIRE_TODO,
//         todoItem: todoItem
//     }
// }

// export function deleteTodo(id: string): TodoActionTypes {
//     return {
//         type: DELETE_TODO,
//         id: id
//     }
```

index.tsx (where I configure the store)

```
import { combineReducers, createStore, applyMiddleware } from "redux"
import { composeWithDevTools } from 'redux-devtools-extension';

import thunk, { ThunkMiddleware } from 'redux-thunk'; //NEW LINE
import { todoReducer } from "./reducers";
import { TodosState } from "./types";
import { AppActions } from "../models/actions";


const rootReducer = combineReducers({
    todoReducer: todoReducer
})

export type RootState = ReturnType<typeof rootReducer>;

export default function configureStore() {
    const store = createStore(
        rootReducer,
        composeWithDevTools(
            applyMiddleware(
                thunk as ThunkMiddleware<TodosState, AppActions>
            ) //NEW FOR THUNK.
        )
    );
    // thunk as ThunkMiddleware<RootState, AppActions>

    return store;
}
```


reducers.ts (My reducer)
```import { TodosState, TodoActionTypes, GETTING_TODO_ITEMS, GOT_TODO_ITEMS } from "./types";

const initialState: TodosState = {
    todoItems: [],
    loading: false
};

export function todoReducer(state = initialState, action: TodoActionTypes): TodosState {
    switch (action.type) {
        case GETTING_TODO_ITEMS:
            return {
                ...state,
                loading: true
            }
        case GOT_TODO_ITEMS:
            return {
                ...state,
                todoItems: action.todoItems,
                loading: true
            }
        default:
            return state;
    }
}
```

types.ts (my types file for redux)

```
import { TodoItem } from "../models/TodoItem";
import { Action } from "redux";

export interface TodosState {
    todoItems: TodoItem[];
    loading: boolean;
}

//Action Type Definitions.
//GET (AKA GET)
export const GETTING_TODO_ITEMS = "GETTING_TODO_ITEMS";
export const GOT_TODO_ITEMS = "GOT_TODO_ITEMS";

//CREATE (AKA POST)
export const CREATING_NEW_TODO = "CREATING_NEW_TODO";
export const CREATED_NEW_TODO = "CREATED_NEW_TODO";

//TOGGLE (AKA PATCH)
export const TOGGLING_DONE_STATUS_FOR_TODO = "TOGGLING_DONE_STATUS_FOR_TODO";
export const TOGGLED_DONE_STATUS_FOR_TODO = "TOGGLED_DONE_STATUS_FOR_TODO";

//UPDATE ENTIRE TODO (AKA PUT)
export const UPDATING_ENTIRE_TODO = "UPDATING_ENTIRE_TODO";
export const UPDATED_ENTIRE_TODO = "UPDATED_ENTIRE_TODO";

//DELETE TODO (AKA DELETE)
export const DELETING_TODO = "DELETING_TODO";
export const DELETED_TODO = "DELETED_TODO";


//Actions. (NOTE ASYNC ACTIONS WITH REDUX THUNK ARE VERY DIFFERENTLY WRITTEN!!!)
//WARNING: Very different from redux actions from before for Async!!!
export interface GettingTodoItems extends Action<typeof GETTING_TODO_ITEMS> {
    todoItems: TodoItem[];
}

export interface GotTodoItems extends Action<typeof GOT_TODO_ITEMS> {
    todoItems: TodoItem[];
}

export interface CreatingNewTodo extends Action<typeof CREATING_NEW_TODO> {
}

export interface CreatedNewTodo extends Action<typeof CREATED_NEW_TODO> {
}

export interface TogglingDoneStatusForTodo extends Action<typeof TOGGLING_DONE_STATUS_FOR_TODO> {
}

export interface ToggledDoneStatusForTodo extends Action<typeof TOGGLED_DONE_STATUS_FOR_TODO> {
}

export interface UpdatingEntireTodo extends Action<typeof UPDATING_ENTIRE_TODO> {
}

export interface UpdatedEntireTodo extends Action<typeof UPDATED_ENTIRE_TODO> {
}

export interface DeletingTodo extends Action<typeof DELETING_TODO> {
}

export interface DeletedTodo extends Action<typeof DELETED_TODO> {
}

export type TodoActionTypes =
    GettingTodoItems | GotTodoItems |
    CreatingNewTodo | CreatedNewTodo |
    TogglingDoneStatusForTodo | ToggledDoneStatusForTodo |
    UpdatingEntireTodo | UpdatedEntireTodo |
    DeletingTodo | DeletedTodo;


//Examples of what doesn't work HERE!
// interface CreatingNewTodo {
//     type: typeof CREATE_NEW_TODO;
//     todoItem: TodoItem;
// }

// interface TogglingDoneStatusForTodo {
//     type: typeof TOGGLE_DONE_STATUS_FOR_TODO;
//     id: string;
// }
// interface UpdatingEntireTodo {
//     type: typeof UPDATE_ENTIRE_TODO;
//     todoItem: TodoItem;
// }
// interface DeletingTodo {
//     type: typeof DELETE_TODO;
//     id: string;
// }
```
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...