react-redux两种实现方式(connect和Hooks)以及TS+Hooks

一、redux的封装

1.通过redux-thunk中间件

Redux store 仅支持同步数据流。使用 thunk 等中间件可以帮助在 Redux 应用中实现异步性。可以将 thunk 看做 store 的 dispatch() 方法的封装器;我们可以使用 thunk action creator 派遣函数或 Promise,而不是返回 action 对象。

注意,没有 thunk 的话,默认地是同步派遣。也就是说,我们依然可以从 React 组件发出 API 调用(例如使用 componentDidMount() 生命周期方法发出这些请求),但是我们在 Redux 应用中难以实现以下两点:

  • 可重用性(思考下合成)
  • 可预测性,只有 action creator 可以是状态更新的单一数据源

要在应用中使用 thunk 中间件,请务必安装 redux-thunk 软件包:

npm install --save redux-thunk

2.安装好中间件之后创建index和reduce文件

//index.js
import { createStore, applyMiddleware, compose } from "redux";
import thunk from 'redux-thunk'
import cRducer from "./reducer";
// redux-devtools
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const store = createStore(cRducer, composeEnhancers(
  applyMiddleware(thunk)
))

export default store
//reducer.js
import { combineReducers } from 'redux-immutable';
import { reducer as store_demo } from 'src/page/store_demo/store/index';

// 多个reducer合并
const cRducer = combineReducers({
     store_demo:store_demo,   //定义每个文件夹下的名称,方便获取
});

export default cRducer;

注:reduce文件中combineReducers用于将若干个reduce进行合并

3.公共的方法封装好之后,在每个页面使用的时候,需要创建创建state和dispatch,如下:

注:当然也可以全部都放在公共创建,这样做是为了更好的维护。

//创建类型
//actionType.js
export const CHANGE_NUM = 'CHANGE_NUM'
//页面文件夹下的reduce

import * as actionTypes from './actionType'

import { Map } from 'immutable'
// 使用Immutable管理redux中的state (修改的`state`不会修改原有数据结构, 而是返回修改后新的数据结构)

const defaultState = Map({
    num:1
})

function reducer(state = defaultState, action) {
  switch (action.type) {
    case actionTypes.CHANGE_NUM:
      return  state.set('num',action.num+1)
    default:
      return state
  }
}

export default reducer
  • 还有一个对action的统一管理,这个可有可无,但是非常推荐使用。在页面使用不用再引入type,直接引入actionCreator编写好的函数,如下:
import * as actionType from './actionType'

export const changeMessageNum = (data) => {
  return {
    type: actionType.CHANGE_NUM,
    data
  };
};

二、使用

1.connect方式

这种方式是通过connect将action方法绑定到props中,使用时直接用props.xx,与传值的形式一样。

import { connect } from "react-redux";
import { changeMessageNum } from "store/Reducer/App/action";
import { bindActionCreators } from "redux";

export default connect(
  (state) => ({
    num: state.num
  }),
  dispatch => bindActionCreators({ changeMessageNum }, dispatch)
)(App);

这种方式写起来代码的重复非常高,每个页面都需要写。不过,react-redux 7.1之后可以使用useSelector、useDispatch等HooksApi替代connect,减少模板代码。

2.React Hooks方式

通过useDispatch, useSelector两个hook对引入state和action中的变量和方法,非常的方便。

//store_demo

import React from 'react';
import {  useDispatch, useSelector } from 'react-redux'
import {getNumAction} from '../store/actionCreator'


const Store_demo = () =>{
  //使用hook获取状态
  const { num } = useSelector(state =>state.store_demo)

  //改变状态
  const dispatch = useDispatch();
  const change_num = () => {
    dispatch(getNumAction(num));
  }
  return (
    <div>
      <div>--{num}--</div>
      <button onClick={change_num}>点击</button>
    </div>
)};


export default Store_demo

三、TS+Hooks

再多提供一种TS封装的方式,和上面基本相似,这里就不多介绍了,直接提供代码。

  • 公共文件
//store下的index.ts
import thunk from "redux-thunk";
import { combineReducers, ReducersMapObject, AnyAction, createStore, applyMiddleware } from "redux";
import { ICombineState } from "store/index.d";
import Demo from "store/Reducer/demo";

const reducers: ReducersMapObject<ICombineState, AnyAction> = {
  demo: Demo,
  //[key]:Value,   这里是将每个页面的store引入,相当于注册
};

const store = applyMiddleware(thunk)(createStore)(combineReducers(reducers));

export default store;
//index.d.ts
export interface IAppState {
  num: number;
}

export interface ICombineState {
  demo: IAppState ;
}
  • 页面单独文件
//index.ts

 import { AnyAction } from "redux";
import { IAppState } from "store/index.d";
import { NUMBER } from "./actionTypes";

const initialSatte: IAppState = {
  num: 0,
};

const reducer = (state: IAppState = initialSatte, action: AnyAction) => {
  switch (action.type) {
    case NUMBER:
      return { ...state, num: action.data };
    default:
      return state;
  }
};
export default reducer;
//actionTypes.ts
// 字体大小
export const NEMBER= Symbol("NEMBER");
//action.ts
import {NEMBER } from "./actionTypes";

export const getNum = (data: number) => {
  return {
    type: ROOT_FONT_SIZE,
    data
  };
};
  • 使用
import { useSelector, useDispatch } from "react-redux";
import { ICombineState } from "store/index.d";
import { changeRootFontSize } from "store/Reducer/App/action";

const { num} = useSelector((state: ICombineState) => state.demo);
const dispatch = useDispatch();

dispatch(changeRootFontSize(20));
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

名字还没想好☜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值