redux + react-redux 完整版

Redux(简单版本)

1.安装redux

npm i redux

2.配置store

// 引入createStore
// store.js
import { createStore } from "redux";
import countReducer from "./count_reducer";
export default createStore(countReducer);

3.使用combineReducers 来组合多个reducer

import { createStore, applyMiddleware, combineReducers } from "redux";
import CountReducer from "./reducers/count";
import UserReducer from "./reducers/user";

import thunk from "redux-thunk";

export default createStore(
  combineReducers({
    count: CountReducer,
    user: UserReducer,
  }),
  applyMiddleware(thunk)
);

4.配置reducer

// count_reducer.js


const countReducer = (prevState = 0, action) => {
  const { type, data } = action;

  switch (type) {
    case "increment":
      return prevState + data;
    case "decrement":
      return prevState - data;

    default:
      return prevState;
  }
};

export default countReducer;


5.组件中使用

store.getState()获取数据

// Count.jsx

import store from "../../redux/store";
const [count,setCount] = useState(store.getState())

<div>当前求和为: {count}</div>

store.dispatch()

const increment = ()=>{
    store.dispatch({type:'increment',data:'xxx'})
}
//这样调用后count 并不会引起变化,此时需要store的另一个api

store.subscribe()

//在类式组件中:这个api 需要在componentDidMount 钩子中调用,并且需要主动调用this.setState()来主动刷新页面重新渲染。
componentDidMount(){
    store.subscribe(()=>{
        this.setState({})  // 传入空对象,目的是让页面再次刷新下
    })
}

// 函数式组件中:
const [count,setCount] = useState(store.getState())

useEffect(()=>{
    store.subscribe(()=>{
        setCount(store.getState())   // 此处目的同样是重新渲染页面
    })
},[])


redux (完善版本)

在简单版本的基础上完善并规范化一些操作。

1.创建常量文件,统一规范

//新建 constant.js

export const INCREMENT = "increment";
export const DECREMENT = "decrement";

​ 在action.js 和 reducer.js 中都引入 常量。

2.规范化操作action

// 之前都是在组件中调用dispatch 
const increment = ()=>{
    store.dispatch({type:'increment',data:'xxx'})
},
这样每次都得来写action。现在把action统一规范到文件中。

新建 count_action.js

import { INCREMENT, DECREMENT } from "./constant";

export const createIncrementAction = (data) => ({
  type: INCREMENT,
  data,
});
export const createDecrementAction = (data) => ({
  type: DECREMENT,
  data,
});

组件中引入

import {
  createIncrementAction,
  createDecrementAction,
} from "../../redux/count_action";

// 直接使用

const increment = () => {
	store.dispatch(createIncrementAction(selectValue));
};
  
const decrement = () => {
  store.dispatch(createDecrementAction(selectValue));
 };
 
 

异步action 和同步action

根据action的类型来进行判断,若action 为一个 Object对象,则为同步。
若 action 为一个函数,则为异步。

使用 redux-thunk中间件来处理异步action

npm i redux-thunk
// store.js

// 引入createStore
import { createStore, applyMiddleware } from "redux";
import thunk from "redux-thunk"; // 引入thunk
import countReducer from "./count_reducer";
export default createStore(countReducer, applyMiddleware(thunk));

// count_action.js

import { INCREMENT, DECREMENT } from "./constant";

export const createIncrementAction = (data) => ({
  type: INCREMENT,
  data,
});
export const createDecrementAction = (data) => ({
  type: DECREMENT,
  data,
});

//此处就是异步action  返回一个函数,在返回的函数中写异步操作就行
export const createIncrementAsync = (data, time) => {
  return (dispatch) => {
    setTimeout(() => {
      dispatch(createIncrementAction(data));
    }, time);
  };
};

react-redux

react官方出的一个操作redux的库,更加方便舒服的在react项目中使用redux

在这里插入图片描述

react-redux的基本使用流程

// 创建容器层 container/count/index.js
// 使用 connnect 来连接UI层和容器层



// ui 组件
import CountUi from "../../components/Count/index";
import { increment } from "../../redux/count_actions";
//使用connect 将 ui组件和 容器组件连接
import { connect } from "react-redux";

const mapStateToProps = (state) => {
  return {
    count: state,
  };
};

const mapDiapatchToProps = (dispatch) => {
  return {
    jia: (number) => dispatch(increment(number)),
  };
};

// !!! 注意 connect 方法的使用

export default connect(mapStateToProps, mapDiapatchToProps)(CountUi);

// 将原来引入<Count /> 组件的地方换成 容器组件
// 将 store 以props 的形式传入

import React from "react";
import Count from "./containers/count";
import store from "./redux/store";
function App() {
  return (
    <>
      <Count store={store} />
    </>
  );
}

export default App;
// count UI 组件中 使用 props 的形式来使用

function Count(props) {
  console.log("props", props);
  const mincrement = () => {
    props.jia(100);
  };
  return (
    <>
      <div>Count is {props.count}</div>
      <button onClick={mincrement}>+</button>
    </>
  );
}

react-redux 的优化

优化一:不必将容器层和ui层分开写了,写到一个文件即可

// components/count/index

import React, { useEffect, useState } from "react";
import { connect } from "react-redux";
import {
  increment,
  decrement,
  asyncIncrement,
} from "../../redux/count_actions";
function Count(props) {
  console.log("props", props);
  const mincrement = () => {
    props.jia(100);
  };
  const mdecrement = () => {
    props.jian(20);
  };
  const masyncIncrement = () => {
    props.asyncJia(30, 1000);
  };

  return (
    <>
      <div>Count is {props.count}</div>
      <button onClick={mincrement}>+</button>
      <button onClick={mdecrement}>-</button>
      <button onClick={masyncIncrement}>async+</button>
    </>
  );
}

export default connect(
  (state) => ({ count: state }),
  // (dispatch) => ({
  //   jia: (number) => dispatch(increment(number)),
  //   jian: (number) => dispatch(decrement(number)),
  //   asyncJia: (num, time) => dispatch(asyncIncrement(num, time)),
  // })
  //简写优化: react-redux 自动帮我们进行了dispatch 分发动作。
  {
    jia: increment,
    jian: decrement,
    asyncJia: asyncIncrement,
  }
)(Count);


优化二: 使用react-redux 提供的Provider ,不用给每个组件都用props来传递store

//原来的是这样: App.jsx

import store from "./redux/store";
function App() {
  return (
    <>
      <Count store={store} />
       {/* 这里有多少个组件都得传递store */}
      {/* <XXX store={store} /> */}
      {/* <XXX store={store} /> */}
      {/* <XXX store={store} /> */}
    </>
  );
}

// 优化后: main.jsx

import store from "./redux/store";
import { Provider } from "react-redux";

ReactDOM.createRoot(document.getElementById("root")).render(
  <Provider store={store}>
    <App />
  </Provider>
);


使用useSelector和useDispatch 替换connect

import { useSelector, useDispatch, connect } from "react-redux";

//原来是使用connect 来 连接ui和数据层,写起来比较麻烦。
// 数据和方法都在props中。

function Page1 (props:any){
    const clickbtn = ()=>{
		props.increment(1)
         // props.decrement(2);
         // props.asyncIncrement(2, 1000);
    }
    return (
    	<>
        	<div>{props.info.name}</div>
        	<button onClick={clickbtn}>+ - </button>
        </>
    )
}


 export default connect((state) => ({ info: (state as any).info }), {
   increment: incrementAction,
   decrement: decrementAction,
   asyncIncrement: asyncIncrementAction,
 })(Page1);



// 现在使用useSelector和useDispatch替换connect 

function Page1 (){
    const info = useSelector(state=>state.info)
    const dispatch = useDispatch() 
    const clickbtn = ()=>{
      //  dispatch(incrementAction(1))
      //   dispatch(decrementAction(2))
        dispatch(asyncIncrementAction(2, 1000) as any)
    }
     return (
    	<>
        	<div>{info.name}</div>
        	<button onClick={clickbtn}>+ - </button>
        </>
    )
    
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值