我在我的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.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;
}
};
这里编译器在<{p>}中的reducers/index.tsx
中说明了这一点
case ADD_USERS:
return {
...state,
users: action.payload === undefined ? [...state.users] : [...state.users, ...action.payload]
};
action.payload
是User
而非Array<User>
是正确的(我已声明减速器的类型为(state: StoreState, action: Action<User>)
)。
我该如何使用它?如果没有替代方案,我将不得不为每个ACTION
编写单独的缩减器,这些缩小器具有不同的payload
,我认为这是不好的。
我使用DispatchProps
类型的方式对我来说也很奇怪。我想针对mapStateToProps
和mapDispatchToProps
的类型关注this。
有没有解决这个问题?
PS:我使用的是react
,redux
和react-redux
个库。
答案 0 :(得分:0)
我找到了解决方案。我不确定这是否是正确的方法。
而不是像这样制作动作类型泛型 -
interface Action<T> {
type: string;
payload?: T;
}
我为每个Action
创建了单独操作类型,然后Reducer接受的操作类型将是|
。
因此,类型看起来像这样(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);
不再有编译错误,payload
和ADD_USER
ADD_USERS
已正确收到。
建议减少操作类型样板here。