react redux Typescript 的使用
新建项目
用create-react-app新建一个react项目
create-react-app xxx --typescript
安装依赖
安装redux
yarn add redux @types/redux react-redux @types/react-redux;
或者
npm install redux @types/redux react-redux @types/react-redux;
创建store
import { createStore, combineReducers, applyMiddleware } from 'redux';
import thunkMiddleware from 'redux-thunk';
import { composeWithDevTools } from 'redux-devtools-extension';
import { systemReducer } from './system/reducers';
import { chatReducer } from './chat/reducers';
const rootReducer = combineReducers({
system: systemReducer,
chat: chatReducer
});
export type AppState = ReturnType<typeof rootReducer>;
export default function configureStore() {
const middlewares = [thunkMiddleware];
// applyMiddleware引入中间件
const middleWareEnhancer = applyMiddleware(...middlewares);
const store = createStore(
rootReducer,
composeWithDevTools(middleWareEnhancer)
);
return store;
}
引用store
import * as React from 'react';
import { render } from 'react-dom';
import { Provider } from 'react-redux';
import configureStore from './store';
import App from './App';
const store = configureStore();
const Root = () => (
<Provider store={store}>
<App />
</Provider>
);
render(<Root />, document.getElementById('root'));
编写组件
typescript的写法就是在class前加上props 和 state的类型,比如:
import React from 'react';
interface IProps{}
interface IState{
xx: string;
yy: number
}
class MyComponent extends React.Component<Props, State> {
constructor(props: IProps) {
super(props);
this.state={
xx: '',
yy: 1
}
}
render(){
return (
<>
...
</>
)
}
}
实例
一个简单的聊天应用程序来演示包含静态类型的可能方法。这个聊天应用程序将有两个 reducer。chat reducer 将专注于存储聊天记录,system reducer 将专注于存储会话信息。
为 State 增加类型检查
向每个 state 切片添加类型是一个很好的开始,因为它不依赖于其他类型。在这个例子中,我们首先描述 chat reducer 相关的 state 切片:
// src/store/chat/types.ts
export interface Message {
user: string
message: string
timestamp: number
}
export interface ChatState {
messages: Message[]
}
然后对 system reducer 相关的 state 切片做同样的处理:
// src/store/system/types.ts
export interface SystemState {
loggedIn: boolean
session: string
userName: string
}
导出的这些 interface,稍后在 reducer 和 action creators 中都能重用它们。
为 Action & Action Creator 增加类型检查
chat Action 常量和形状:
// src/store/chat/types.ts
export const SEND_MESSAGE = 'SEND_MESSAGE'
export const DELETE_MESSAGE = 'DELETE_MESSAGE'
interface SendMessageAction {
type: typeof SEND_MESSAGE
payload: Message
}
interface DeleteMessageAction {
type: typeof DELETE_MESSAGE
meta: {
timestamp: number
}
}
export type ChatActionTypes = SendMessageAction | DeleteMessageAction
此处使用 TypeScript 的联合类型来表达所有可能的操作。
声明这些类型后,我们现在还可以对 chat 的 action creator 做类型检查。在这种情况下,我们利用 TypeScript 的 inference:
// src/store/chat/actions.ts
import { Message, SEND_MESSAGE, DELETE_MESSAGE } from './types'
// TypeScript infers that this function is returning SendMessageAction
export function sendMessage(newMessage: Message) {
return {
type: SEND_MESSAGE,
payload: newMessage
}
}
// TypeScript infers that this function is returning DeleteMessageAction
export function deleteMessage(timestamp: number) {
return {
type: DELETE_MESSAGE,
meta: {
timestamp
}
}
}
system action 常量和形状:
// src/store/system/types.ts
export const UPDATE_SESSION = 'UPDATE_SESSION'
interface UpdateSessionAction {
type: typeof UPDATE_SESSION
payload: SystemState
}
export type SystemActionTypes = UpdateSessionAction
有了这些类型,现在也可以对 system 的 action creator 做类型检查:
// src/store/system/actions.ts
import { SystemState, UPDATE_SESSION } from './types'
export function updateSession(newSession: SystemState) {
return {
type: UPDATE_SESSION,
payload: newSession
}
}
为 reducer 增加类型检查
reducer 只是纯函数,它输入 先前的 state 和一个 action 然后返回下一个 state。在此示例中,我们显式声明此 reducer 将接收的 action 类型以及它应返回的内容(适当的 state 切片)。 通过这些添加,TypeScript 将在我们的 action 和 state 的属性上提供丰富的智能感知。
// src/store/chat/reducers.ts
import {
ChatState,
ChatActions,
ChatActionTypes,
SEND_MESSAGE,
DELETE_MESSAGE
} from './types'
const initialState: ChatState = {
messages: []
}
export function chatReducer(
state = initialState,
action: ChatActionTypes
): ChatState {
switch (action.type) {
case SEND_MESSAGE:
return {
messages: [...state.messages, action.payload]
}
case DELETE_MESSAGE:
return {
messages: state.messages.filter(
message => message.timestamp !== action.meta.timestamp
)
}
default:
return state
}
}
已增加类型检查的 system reducer:
// src/store/system/reducers.ts
import {
SystemActions,
SystemState,
SystemActionTypes,
UPDATE_SESSION
} from './types'
const initialState: SystemState = {
loggedIn: false,
session: '',
userName: ''
}
export function systemReducer(
state = initialState,
action: SystemActionTypes
): SystemState {
switch (action.type) {
case UPDATE_SESSION: {
return {
...state,
...action.payload
}
}
default:
return state
}
}
生成 root reducer 函数,通常使用 combineReducers 来完成。请注意,我们不必为 AppState 显式声明新接口。 我们可以使用 ReturnType 从 rootReducer 推断状态形状。
// src/store/index.ts
import { systemReducer } from './system/reducers'
import { chatReducer } from './chat/reducers'
const rootReducer = combineReducers({
system: systemReducer,
chat: chatReducer
})
export type AppState = ReturnType<typeof rootReducer>
对 mapStateToProps 接收的参数添加类型检查,将 action creator 映射到组件的 props 中
// src/App.tsx
import React, {Component} from 'react'
import {connect} from 'react-redux'
import { AppState } from './store'
import { SystemState } from './store/system/types'
import { updateSession } from './store/system/actions'
import { ChatState } from './store/chat/types'
import { sendMessage } from './store/chat/actions'
interface AppProps {
chat: ChatState
system: SystemState
sendMessage: typeof sendMessage
updateSession: typeof updateSession
}
class App extends Component<AppProps>{
}
const mapStateToProps = (state: AppState) => (
// 此处的类型将在AppProps处校验
{
system: state.system,
chat: state.chat
}
)
export default connect(mapStateToProps, { updateSession,sendMessage })(App)
网友评论