我有一个名为Messages的reducer,它将具有以下操作:
- GET_MESSAGES_START→它开始使用API加载10条最近的消息
- GET_MESSAGES_SUCCESS→使用API 完成10条最近消息的加载
- GET_MESSAGES_FAIL→API失败
- RESET_MESSAGE→删除特定用户的消息/收件箱
- GET_SOCKET_MESSAGE→从套接字获取消息
GET_MESSAGE_START,RESET_MESSAGE→有效载荷为{chatUser: "username"}
GET_MESSAGE_SUCCESS→有效载荷为{chatUser: "username",nextPage: 2,count: 22,messages:Array<InboxMessages>}
GET_MESSAGE_FAIL→有效载荷为{error:[Error]}
GET_SOCKET_MESSAGE→有效载荷为{chatUser: "username", message: <InboxMessages> }
界面
// For Reusing
export interface errorInterface{
error?:null|string|Array<string>|{[key:string]:any}
}
// For Reusing
export interface BaseLoadingInterface {
loading: boolean
}
// For Reusing
export interface NextPageInterface {
nextPage: number | null
}
export interface InboxMessages {
id: number,
user: userInterface,
receiver: userInterface,
message: string,
timestamp: Date,
thread: number,
attachment: any
}
export interface MessageInboxInterface extends BaseLoadingInterface, NextPageInterface{
user: string,
messages: Array<InboxMessages>,
count: number,
}
export interface MessageStateInterface extends errorInterface{
chatUser: string | null,
inbox: Array<MessageInboxInterface>
}
export interface MessagePayload {
chatUser: string,
nextPage: null | number,
count: number,
messages: Array<InboxMessages>
}
export interface MessageStartInterface {
type: typeof GET_MESSAGES_START | typeof RESET_MESSAGE,
payload:{
chatUser: string
}
}
export interface MessageSuccessInterface{
type: typeof GET_MESSAGES_SUCCESS,
payload:MessagePayload
}
export interface MessageFailInterface {
type: typeof GET_MESSAGES_FAIL,
payload: errorInterface
}
export interface SocketMessageInterface{
type: typeof GET_SOCKET_MESSAGE,
payload: InboxMessages
}
export type MessageAction = MessageStartInterface | MessageSuccessInterface | SocketMessageInterface
齿轮
const defaultMessagesState:MessageStateInterface = {
chatUser:null,
error:null,
inbox:[],
};
export const userChatMessageReducer = (state:MessageStateInterface=defaultMessagesState, action:MessageActionInterface) => {
const{type,payload}=action;
const chatUserInbox = state.inbox.filter(el => el.user === payload.chatUser);
const inbox = state.inbox.filter(el => el.user !== payload.chatUser);
switch (type) {
case GET_MESSAGES_START:
// Returns a updated User Inbox
getMessageStartInbox(state, payload)
return{
...state,
chatUser:payload.chatUser,
inbox: inbox
};
case GET_MESSAGES_SUCCESS:
// Returns a updated Inbox with messages
return {
...state,
inbox: [...inbox,getInboxMessage(state, payload)]
};
case GET_SOCKET_MESSAGE:
// Initiate New Message From Socket and returns new message
return {
...state,
inbox: [...inbox,newInboxObject(state, payload.message)]
};
case RESET_MESSAGE:
// Delete chat user's message
return {
...state,
inbox:[...inbox]
};
case GET_MESSAGES_FAIL:
return {
...state,
error: payload.error
};
default:
return state
}
};
但我得到错误,说,chatUser,消息,消息不在MessageActionInterface ->有效载荷类型。这些不是MessageActionInterface.payload的有效类型
在switch语句的分支中出现错误的原因是由于一个小的技术问题。当你在switch
语句之外解构action
对象时,Typescript会同时给type
和payload
赋值一个类型。它们现在有了自己的类型,所以Typescript不会考虑它们之间的关系。switch
的每个case
都细化了type
的类型定义,但没有细化payload
的类型定义。
action
对象。使用switch (action.type)
,用action.payload
替换对payload
的引用。
还有一个潜在的问题,即在switch
之外访问payload.chatUser
以生成inbox
。似乎不是所有的动作类型都有chatUser
属性(InboxMessages
中的user
应该是chatUser
吗?)。
我们可以使用保护'chatUser' in action.payload
来有条件地访问chatUser
,以确保该属性存在。如果没有,则返回null
,并获得inbox
的空数组。
const chatUser = ( 'chatUser' in action.payload ) ? action.payload.chatUser : null;
const inbox = state.inbox.filter(el => el.user !== chatUser);