React+TypeScript如何使用Redux

本文详细介绍了如何在React+TypeScript环境中搭建并使用Redux。从安装依赖,创建store,定义reducer,到在组件中使用connect及配合Hook使用,展示了完整的Redux集成步骤。同时,示例中包含了类组件和函数式组件的Redux状态管理和操作。
摘要由CSDN通过智能技术生成

记录一下React+TypeScript如何使用redux

一、截至本篇文章发布依赖均为最新版本,版本号如下

"@types/react": "^17.0.37",
"@types/react-dom": "^17.0.11",
"@types/react-redux": "^7.1.20",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-redux": "^7.2.6",
"react-router-dom": "^6.0.2",
"react-scripts": "4.0.3",
"redux": "^4.1.2",
"redux-devtools-extension": "^2.13.9",
"typescript": "^4.1.2",

二、初始化redux

本文主要记录redux使用react+ts环境搭建可参照其他文章

1、安装依赖
yarn add redux react-redux @types/react-redux redux-devtools-extension
2、新建目录结构如下

store目录结构

3、store代码如下
  • store入口文件 /store/index.ts
import { applyMiddleware, createStore } from "redux";
import { composeWithDevTools } from "redux-devtools-extension";  /*  使用redux调试工具  */
import reducers from "./reducers";

export type rootState = ReturnType<typeof reducers>;
const store = createStore(reducers, composeWithDevTools(applyMiddleware()));
export default store;

  • reducer入口文件 /store/reducers/index.ts
import { combineReducers } from "redux";
import user from "./user";
export default combineReducers({ user });
  • user模块reducer /store/reducers/user.ts
export interface IUser {
  id: string;
  name: string;
  role: string;
}

export interface IUserState {
  user: IUser;
}

const initUserState: IUserState = {
  /* state默认值 */
  user: {
    id: "default",
    name: "普通用户",
    role: "user",
  },
};

export enum IUserActionType {
  /* Actions */
  INIT,
  CHANGE,
}

const user = (
  state: IUserState = initUserState,
  action: { type: IUserActionType; payload: any }
) => {
  const { payload } = action;
  switch (action.type) {
    case IUserActionType.INIT:
      return state;
    case IUserActionType.CHANGE:
      return { ...state, user: { ...state.user, ...payload } };
    default:
      return state;
  }
};

export default user;

4、在项目入口文件index.tsx内注入store
import React from 'react';
import ReactDOM from 'react-dom';
import '@/assets/styles/default.less';
import App from './App';
import reportWebVitals from './reportWebVitals';

import { Provider } from 'react-redux';   /*  redux使用  */
import store from './store';  /*  redux使用  */

ReactDOM.render(
  <Provider store={store}>  /*  redux使用  */
    <React.StrictMode>
      <App />
    </React.StrictMode>
  </Provider>,
  document.getElementById('root')
);

reportWebVitals();

三、在组件中使用

  • action最好提取到统一文件内方便复用,本文为方便演示未提取
1、在类组件中使用
/* 类组件使用redux */

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?: (name: string) => void
}

class ClassComp extends Component<IProps> {
  protected handleChangeName(name: string) {
    this.props.changeName && this.props.changeName(name)
  }
  render() {
    const { name } = this.props.user
    return (
      <div>
        {name}
        <br />
        <button onClick={() => { this.handleChangeName("张三") }}>ClassComp改变名字</button>
      </div>
    )
  }
}

const mapStateToProps = (state: rootState) => {
  return { ...state.user }
}

const mapDispatchToProps = (dispatch: Dispatch) => ({
  changeName: (name: string) => {
    dispatch({
      type: IUserActionType.CHANGE,
      payload: { name }
    })
  }
})

export default connect(mapStateToProps, mapDispatchToProps)(ClassComp)
2、在函数式组件中使用
/* 函数式组件使用redux */

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?: (name: string) => void
}

function FnComp(props: IProps) {
  const { user: { name }, changeName } = props
  const handleChangeName = (name: string) => {
    changeName && changeName(name)
  }
  return (
    <div>
      {name}
      <br />
      <button onClick={() => { handleChangeName("李四") }}>FnComp改变名字</button>
    </div>
  )
}

const mapStateToProps = (state: rootState) => {
  return { ...state.user }
}

const mapDispatchToProps = (dispatch: Dispatch) => ({
  changeName: (name: string) => {
    dispatch({
      type: IUserActionType.CHANGE,
      payload: { name }
    })
  }
})

export default connect(mapStateToProps, mapDispatchToProps)(FnComp)
3、配合Hook使用
/* Hook使用redux */

import React from 'react'
import { useDispatch, useSelector } from 'react-redux'
import { rootState } from '@/store/index'
import { IUserState, IUserActionType } from '@/store/reducers/user'

export default function HookComp() {
  const { user } = useSelector<rootState, IUserState>((state) => state.user)
  const dispatch = useDispatch()
  const handleChangeName = (name: string) => {
    dispatch({
      type: IUserActionType.CHANGE,
      payload: { name }
    })
  }
  return (
    <div>
      {user.name}
      <br />
      <button onClick={() => { handleChangeName("王五") }}>HookComp改变名字</button>
    </div>
  )
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值