Redux 与 react-redux 使用总结

image

Redux = Reducer + Flux

1. redux 基本使用

1.1 安装

安装 redux

npm install redux

安装 redux-thunk(如需支持异步 action)

npm install redux-thunk

1.2 使用示例代码

工程目录

src
├─ components
│  └─ Count
│    └─ index.jsx
├─ redux
│  ├─ count
│  │  ├─ action.js
│  │  ├─ constant.js
│  │  └─ reducer.js
│  ├─ person
│  └─ store.js
├─ App.jsx
└─ index.jsx

index.js (入口文件)

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import store from './redux/store';

ReactDOM.render(<App />, document.getElementById('root'));

// 监测redux状态的改变,重新渲染App组件(react-redux不用手动监测,包裹 Provider 实现)
store.subscribe(() => {
  ReactDOM.render(<App />, document.getElementById('root'));
});

redux/store.js

import { createStore, applyMiddleWare, combineReducers } from "redux";
import thunk from "redux-thunk"; // 用于支持异步 action
import countReducer from "./count/reducer";
import personReducer from "./person/reducer";

// 最简使用
// export default createStore(reducer);

// 支持异步
// export default createStore(reducer, applyMiddleWare(thunk));

// 支持多个 reducer
const reducer = combineReducers({
  count: countReducer,
  person: personReducer
});
export default createStore(reducer, applyMiddleWare(thunk));

redux/count/constant.js

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

redux/count/reducer.js

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

const initState = 0 // 初始化状态
export default function countReducer(preState = initState, action) {
  const { type, data } = action
  switch (type) {
    case INCREMENT:
      return preState + data;
    case DECREMENT:
      return preState - data;
    default:
      return preState;
  }
}

redux/count/action.js

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

// 同步 action(返回对象)
export const increment = (data) => ({ type: INCREMENT, data });
export const decrement = (data) => ({ type: DECREMENT, data });

// 异步 action(返回函数。一般会在异步任务返回时,调用同步action)
export const incrementAsync = (data, time) => {
  return (dispatch) => {
    setTimeout(() => {
      dispatch(increment(data));
    }, time);
  };
};

components/Count/index.jsx (应用层)

import store from 'redux/count/store';
import { increment, incrementAsync } from 'redux/count/action'

export default class Count extends Component {
  increment = () => {
    const {value} = this.selectNumber
    store.dispatch(increment(value*1));
  };

  incrementAsync = () => {
    const {value} = this.selectNumber
    store.dispatch(incrementAsync(value*1, 500));
  };
  render() {
    return <div>
      <h1>当前求和为:{this.props.count}</h1>
      <select ref={c => this.selectNumber = c}>
        <option value="1">1</option>
        <option value="2">2</option>
      </select>
      <button onClick={this.increment}>+</button>
    </div>
  }
}

2. react-redux 基本使用

2.1 安装

npm install react-redux

2.2 使用示例代码

工程目录

src
├─ containers
│  └─ Count
│    └─ index.jsx
├─ redux
│  ├─ count
│  │  ├─ action.js
│  │  ├─ constant.js
│  │  └─ reducer.js
│  ├─ person
│  └─ store.js
├─ App.jsx
└─ index.jsx

index.js (入口文件)

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import store from './redux/store';
import { Provider } from 'react-redux';

// 用 Provider 包裹,1. 监测redux状态的改变,重新渲染 App 组件 2. 将 store 传给所有后代组件
ReactDOM.render(<Provider store={store}><App /></Provider>, document.getElementById('root'));

App.jsx

import React, { Component } from 'react';
import Count from './containers/Count';
// import store from './store';

export default class App extends Component {
  render() {
    return (
      <div>
        {/* 将 store 传个容器组件(入口文件使用 Provider 后,不用传) */}
        {/* <Count store={store} /> */}
        <Count />
      </div>
    );
  }
}

containers/Count/index.jsx(应用层)——定义UI组件与container组件

import React, { Component } from 'react';
import { connect } from 'react-redux'
import { increment } from '../../redux/count/action'

// 定义UI组件
class Count extends Component {
  increment = () => {
    const {value} = this.selectNumber
    this.props.increment(value*1);
  };
  render() {
    return <div>
      <h1>当前求和为:{this.props.count}</h1>
      <select ref={c => this.selectNumber = c}>
        <option value="1">1</option>
        <option value="2">2</option>
      </select>
      <button onClick={this.increment}>+</button>
    </div>
  }
}

// 映射状态(返回一个对象,key作为UI组件的props)
const mapStateToProps = state => ({ count: state.count, person: state.person})

// 映射操作状态的方法(返回一个对象,key作为UI组件的props)
// const mapDispatchToProps = dispatch => ({
//     add: val => dispatch(increment(val))
// })

// mapDispatchToProps 简写
const mapDispatchToProps = {
  increment: increment
}

export default connect(mapStateToProps, mapDispatchToProps)(Count);

3. Redux DevTools 使用

3.1 安装浏览器插件 Redux DevTools

3.2 项目配置

npm install redux-devtools-extension
// redux/store.js
import { createStore, applyMiddleWare, combineReducers } from "redux";
import thunk from "redux-thunk";
import countReducer from "./count/reducer";
import personReducer from "./person/reducer";
import { composeWithDevTools } from 'redux-devtools-extension'


// 不使用插件调试
// export default createStore(
//   reducer,
//   import.meta.env.REACT_APP_MODE === "development" &&
//   window.__REDUX_DEVTOOLS_EXTENSION__ &&
//   window.__REDUX_DEVTOOLS_EXTENSION__()
// );

// 使用插件调试
const reducer = combineReducers({
  count: countReducer,
  person: personReducer
});
// export default createStore(reducer, composeWithDevTools(); // 无异步
export default createStore(reducer, composeWithDevTools(applyMiddleWare(thunk)); // 有异步

3.3 重启项目

4. 参考资料

  1. https://www.ruanyifeng.com/blog/2016/09/redux_tutorial_part_one_basic_usages.html
posted @ 2023-02-24 19:21  Better-HTQ  阅读(2)  评论(0编辑  收藏  举报