当前位置:
首页
文章
前端
详情

react-redux-typescript

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)

免责申明:本站发布的内容(图片、视频和文字)以转载和分享为主,文章观点不代表本站立场,如涉及侵权请联系站长邮箱:xbc-online@qq.com进行反馈,一经查实,将立刻删除涉嫌侵权内容。