簡體   English   中英

React-Redux中TypeScript中化簡器的類型錯誤

[英]Error in Types for the reducers in TypeScript in React-Redux

我正在為我的React-Redux應用程序使用TypeScript。 我遵循TypeScript React Starter ,但是,上面提到的示例沒有任何帶有某些參數/有效載荷的操作方法。

我有一個簡單的要求-

顯示名稱列表,並在單擊按鈕時添加新名稱。 單擊另一個按鈕時,將添加2個名稱。


應用index.tsx的入口點看起來像這樣-

import * as React from 'react';
import * as ReactDOM from 'react-dom';
import registerServiceWorker from './registerServiceWorker';
import './index.css';
import { createStore } from 'redux';
import { StoreState } from './types';
import { listUsers } from './reducers';
import { Provider } from 'react-redux';
import ListUsers from './containers/ListUsers';

const store = createStore<StoreState>(listUsers, {
  'users': [
    {
      'id': 0,
      'firstName': 'Aniyah',
      'lastName': 'Luettgen',
      'phone': '861-332-5113',
      'email': 'Danika.Ryan84@yahoo.com',
      'role': 'admin'
    },
    {
      'id': 1,
      'firstName': 'Alisa',
      'lastName': 'Pacocha',
      'phone': '085-056-3901',
      'email': 'Eusebio68@yahoo.com',
      'role': 'admin'
    }
  ]
});

ReactDOM.render(
  <Provider store={store}>
    <ListUsers/>
  </Provider>,
  document.getElementById('root') as HTMLElement
);
registerServiceWorker();

常量文件( constants/index.tsx )看起來像這樣-

export const LIST_USERS = 'LIST_USERS';
export type LIST_USERS = typeof LIST_USERS;

export const ADD_USER = 'ADD_USER';
export type ADD_USER = typeof ADD_USER;

export const ADD_USERS = 'ADD_USERS';
export type ADD_USERS = typeof ADD_USERS;

類型( types/index.tsx )是-

export interface User {
  id: number;
  firstName: string;
  lastName: string;
  phone: string;
  email: string;
  role: string;
}

export interface StoreState {
  users: Array<User>;
}

export interface Action<T> {
  type: string;
  payload?: T;
}

我的組件( components/ListUsers.tsx )看起來像這樣-

import * as React from 'react';
import { DispatchProps, ListUsersProps } from '../containers/ListUsers';
import { User } from '../types';

interface ListState {
  counter: number;
}

class ListUsers extends React.Component<ListUsersProps & DispatchProps, ListState> {

  constructor(props: ListUsersProps & DispatchProps) {
    super(props);

    this.addUser = this.addUser.bind(this);
    this.addMultipleUser = this.addMultipleUser.bind(this);

    this.state = {
      counter: 0
    };
  }

  render() {
    return (
      <div>
        <button onClick={() => this.addUser()}>Add User</button>
        <button onClick={() => this.addMultipleUser()}>Add User</button>
        {this.props.users.map((user: User) => (
          <div key={user.id}>{user.firstName}</div>
        ))}
      </div>
    );
  }

  private addUser() {
    this.props.addUser({
      id: this.state.counter,
      firstName: 'abcd',
      lastName: 'efgh',
      email: 'abcd@gmail.com',
      phone: '1234567890',
      role: 'admin'
    });
    this.setState({
      ...this.state,
      counter: this.state.counter + 1
    });
  }

  private addMultipleUser() {
    this.props.addUsers([{
      id: this.state.counter,
      firstName: 'abcd',
      lastName: 'efgh',
      email: 'abcd@gmail.com',
      phone: '1234567890',
      role: 'admin'
    }, {
      id: this.state.counter,
      firstName: 'ijkl',
      lastName: 'mnop',
      email: 'ijkl@gmail.com',
      phone: '1234567890',
      role: 'admin'
    }]);
    this.setState({
      ...this.state,
      counter: this.state.counter + 2
    });
  }
}

export default ListUsers;

我的容器組件( containers/ListUsers.tsx )看起來像這樣-

import { connect, Dispatch } from 'react-redux';
import { Action, StoreState, User } from '../types';
import ListUsers from '../components/ListUsers';
import { addUser, addUsers } from '../actions';

export interface ListUsersProps {
  users: Array<User>;
}

export interface DispatchProps {
  addUser(user: User): Action<User>;
  addUsers(users: Array<User>): Action<Array<User>>;
}

export const mapStateToProps = (state: StoreState): ListUsersProps => {
  return {
    users: state.users
  };
};

export const mapDispatchToProps = (dispatch: Dispatch<DispatchProps>) => {
  return {
    addUser: (user: User) => dispatch(addUser(user)),
    addUsers: (users: Array<User>) => dispatch(addUsers(users))
  };
};

export default connect<ListUsersProps, DispatchProps, {}>(mapStateToProps, mapDispatchToProps)(ListUsers);

現在這是我面臨問題的reducers/index.tsxreducers/index.tsx )-

import { Action, StoreState, User } from '../types';
import { ADD_USER, ADD_USERS, LIST_USERS } from '../constants';

export const listUsers = (state: StoreState, action: Action<User>): StoreState => {
  switch (action.type) {
    case LIST_USERS:
      return state;
    case ADD_USER:
      return {
        ...state,
        users: action.payload === undefined ? [...state.users] : [...state.users, action.payload]
      };
    case ADD_USERS:
      return {
        ...state,
        users: action.payload === undefined ? [...state.users] : [...state.users, ...action.payload]
      };
    default:
      return state;
  }
};

這里的編譯器說在reducers/index.tsx

case ADD_USERS:
  return {
    ...state,
    users: action.payload === undefined ? [...state.users] : [...state.users, ...action.payload]
  };

action.payloadUser而不是Array<User> ,這是正確的(我已將reducer聲明為類型(state: StoreState, action: Action<User>) )。

我該如何處理? 如果沒有其他選擇,我將不得不為每個具有不同payload ACTION編寫單獨的reducer,我認為這是不好的。

我使用DispatchProps類型的方式在我看來也很奇怪。 我試圖按照為各類mapStateToPropsmapDispatchToProps

有什么解決辦法嗎?

PS:我正在使用reactreduxreact-redux庫。

我找到了解決方案。 我不確定這樣做是否正確。


與其像這樣使動作類型通用,不如說是-

interface Action<T> { 
  type: string;
  payload?: T;
}

我為每個Action創建了一個單獨的動作類型 ,然后減速器接受的動作類型將為| 其中。


因此,類型看起來像這樣( types/index.tsx )-

import { ADD_USER, ADD_USERS, LIST_USERS } from '../constants';

export interface User {
  id: number;
  firstName: string;
  lastName: string;
  phone: string;
  email: string;
  role: string;
}

export interface StoreState {
  users: Array<User>;
}

export type ListUsersAction = {type: typeof LIST_USERS};
export type AddUserAction = {type: typeof ADD_USER, payload: User};
export type AddUsersAction = {type: typeof ADD_USERS, payload: Array<User>};

export type Actions = ListUsersAction | AddUserAction | AddUsersAction;

容器組件( containers/ListUsers.tsx )看起來像這樣-

import { connect, Dispatch } from 'react-redux';
import { AddUserAction, AddUsersAction, StoreState, User } from '../types';
import ListUsers from '../components/ListUsers';
import { addUser, addUsers } from '../actions';

export interface ListUsersProps {
  users: Array<User>;
}

export interface DispatchProps {
  addUser(user: User): AddUserAction;
  addUsers(users: Array<User>): AddUsersAction;
}

export const mapStateToProps = (state: StoreState): ListUsersProps => {
  return {
    users: state.users
  };
};

export const mapDispatchToProps = (dispatch: Dispatch<DispatchProps>) => {
  return {
    addUser: (user: User) => dispatch(addUser(user)),
    addUsers: (users: Array<User>) => dispatch(addUsers(users))
  };
};

export default connect<ListUsersProps, DispatchProps>(mapStateToProps, mapDispatchToProps)(ListUsers);

不再有編譯錯誤,並且已正確接收ADD_USERADD_USERS payload


還有就是要減少操作類型樣板推薦這里

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM