1. 程式人生 > 其它 >react+redux+ts

react+redux+ts

react+redux+ts

1. 初始化專案

yarn create react-app my-app --template typescript

2.安裝依賴

yarn add redux react-redux redux-devtools-extension

3.建立store

  1. src/store/reducer/user.ts
 export interface IUser {
   id: number,
   name: string
 }
 interface IState {
   user: IUser
 }
 const initUserState: IState = {
   user: {
     id: 0,
     name: ''
   }
 }
 export enum IUserActionType {
   INIT,
   CHANGE,
 }
 const user = (state:IState = initUserState, action: { type: IUserActionType, payload: any }) => {
   switch (action.type) {
     case IUserActionType.INIT:
       return state
     case IUserActionType.CHANGE:
       return {...state, ...action.payload}
     default:
       return state
   }
 }
 export default user
  1. src/store/index.ts
import { combineReducers } from "redux";
import user from "./user";

export default combineReducers({user})
  1. src/store/index.ts
import { createStore, applyMiddleware } from "redux";
import { composeWithDevTools } from "redux-devtools-extension";
import reducers from "./reducers";
export type rootState = ReturnType<typeof reducers>
const store = createStore(reducers, composeWithDevTools(applyMiddleware()))
export default store

4. 元件使用

  1. 類元件
 import React, { Component } from 'react'
 import { connect } from 'react-redux'
 import { Dispatch } from 'redux'
 import { rootState } from './store'
 import { IUser, IUserActionType } from './store/reducers/user'
 interface IProps {
   user?: IUser,
   changeName?(): void
 }
 class Example extends Component<IProps> {
   handleChangeName = () => {
     this.props.changeName && this.props.changeName()
   }
   render() {
     return (
       <div>
         <div>{this.props.user?.name || '111'}</div>
         <button onClick={this.handleChangeName}>ok</button>
       </div>
     )
   }
 }
 const mapStateToProps = (state: rootState) => {
   return {...state.user}
 }
 const mapDispatchToProps = (dispatch: Dispatch) => {
   return {
     changeName: () => {
       dispatch({
         type: IUserActionType.CHANGE,
         payload: { user: { name: 'abcd' + Date.now()} }
       })
     }
   }
 }
 export default connect(mapStateToProps, mapDispatchToProps)(Example)
  1. 函式元件
import React from 'react'
import { connect } from 'react-redux'
import { Dispatch } from 'redux'
import { rootState } from './store'
import { IUser, IUserActionType } from './store/reducers/user'
interface IProps {
  user?: IUser,
  changeName?(): void
}
const Example1: React.FC<IProps> = (props) => {
  const handleChangeName = () => {
    props.changeName && props.changeName()
  }
  return (
    <div>
      <div>{props.user?.name || '111'}</div>
      <button onClick={handleChangeName}>ok</button>
    </div>
  )
}
const mapStateToProps = (state: rootState) => {
  return {...state.user}
}
const mapDispatchToProps = (dispatch: Dispatch) => {
  return {
    changeName: () => {
      dispatch({
        type: IUserActionType.CHANGE,
        payload: { user: { name: 'abcd' + Date.now()} }
      })
    }
  }
}
export default connect(mapStateToProps, mapDispatchToProps)(Example1)
  1. 函式元件+hooks
import React from 'react'
import { useDispatch, useSelector } from 'react-redux'
import { rootState } from './store'
import { IUserActionType } from './store/reducers/user'
const Example2: React.FC = () => {
  const { user } = useSelector((state: rootState) => state.user)
  const dispatch = useDispatch()
  const handleChangeName = () => {
    dispatch({
      type: IUserActionType.CHANGE,
      payload: { user: { name: 'abcd' + Date.now()} }
    })
  }
  return (
    <div>
      <div>{user?.name || '111'}</div>
      <button onClick={handleChangeName}>ok</button>
    </div>
  )
}
export default Example2