Redux的使用和在 React 中使用 redux

React Redux

一、Redux

# 下载 redux
npm i redux

1. redux的简单使用:

const redux = require("redux");

// 初始化 state
const initState = {
  count: 0
}

// reducer,纯函数
function reducer(state = initState, action) {
  switch (action.type) {
    case "incremnet":
      return { ...state, count: state.count + 1 };
    case "decremnet":
      return { ...state, count: state.count - 1 };
    case "add_number":
      return { ...state, count: state.count + action.data };
    case "sub_number":
      return { ...state, count: state.count - action.data };
    default:
      return state
  }
}

// store
const store = redux.createStore(reducer);

// 订阅 store 中 state 的改变
store.subscribe(() => {
  console.log("state改变了", store.getState());
})

// action
const action1 = { type: "incremnet" };
const action2 = { type: "decremnet" };
const action3 = { type: "add_number", data: 5 };
const action4 = { type: "sub_number", data: 8 };

// dispatch
store.dispatch(action1);
store.dispatch(action2);
store.dispatch(action3);
store.dispatch(action4);

输出结果:

# state改变了 { count: 1 }
# state改变了 { count: 0 }
# state改变了 { count: 5 }
# state改变了 { count: -3 }

2. redux的文件结构使用

使用redux的文件结构:

- store
  -- actions	# 文件夹,存放 actionCreators 函数
  -- reducers	# 文件夹,存放创建 reducer 函数
     --- index.js  # 合并 reducer 
  -- index.js	# 整合 store 对象,并export 导出
  -- constants.js	# 存放 redux 中 action 使用的 type 类型

2.1 redux代码

store/constants.js

/**
 * 用于保存 action中 type 常量值
 */
export const INCREMENT = "increment"
export const DECREMENT = "decrement"
export const ADD_PERSON = "add_person"

store/actions/count.js

import { INCREMENT, DECREMENT } from '../constants'

export function createIncrementAction(data) {
  return {
    type: INCREMENT,
    data
  }
}

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

store/actions/person.js

import { ADD_PERSON } from '../constants'

// 创建增加一个人的 action
export function createAddPerson(data) {
  return {
    type: ADD_PERSON,
    data
  }
}

store/reducers/count.js

import { INCREMENT, DECREMENT } from '../constants'

export default function countReducer(state = 0, action) {
  switch (action.type) {
    case INCREMENT:
      return state + action.data;
    case DECREMENT:
      return state - action.data;
    default:
      return state;
  }
}

store/reducers/person.js

import { ADD_PERSON } from "../constants"

const initState = [
  { id: "001", name: "小李", age: 18 },
  { id: "002", name: "刘哲", age: 25 },
]
export default function personReducer(prevState = initState, action) {
  switch (action.type) {
    case ADD_PERSON:
      return [...prevState, action.data];
    default:
      return prevState;
  }
}

store/index.js

import { createStore, combineReducers } from 'redux'
// 引入 count 的 reducer
import countReducer from './reducers/count.js'
// 引入 person 的 reducer
import personReducer from "./reducers/person.js"

// 合并 reducer,key:value 形式存在 store 中
const allReducers = combineReducers({
  count: countReducer,
  person: personReducer
})

// 暴露 store 对象
export default createStore(allReducers)

2.2 使用 redux

store 文件夹同一层级 创建 index.js

import store from "./store/index.js"

import { createIncrementAction, createDecrementAction } from "./store/actions/count.js"

store.subscribe(() => {
  console.log(store.getState().count);
})
store.dispatch(createIncrementAction(2));
store.dispatch(createDecrementAction(4));
store.dispatch(createDecrementAction(3));
store.dispatch(createIncrementAction(6));
/*
	2
	-2
	-5
	1
*/

3. 异步 action

一般 action 都是 同步的,即返回 对象格式的。

而异步 action 则是 返回 函数形式

// 异步 action,返回 函数
export function createAsyncIncrement(data, delay) {
  // 异步 action 返回函数 可以有两个参数
  return (dispatch, getState) => {
    // 模仿异步请求
    setTimeout(() => {
      dispatch("创建action的函数"(data))
    }, delay)
  }
}

store 需要配置使用 异步中间件 redux-thunk

import { createStore, applyMiddleware, combineReducers, compose } from 'redux'
// 引入 redux-thunk ,异步 action
import thunk from 'redux-thunk'

export default createStore(allReducers, applyMiddleware(thunk))

4. 使用 redux 的Chrome插件

  1. 首先下载浏览器扩展 Redux DevTools,Chrome谷歌商店下载即可

  2. 配置 store 对象

    import { compose } from 'redux'
    
    // 使用compose,强化
    const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose
    
    // 如果使用了异步中间件
    export default createStore(allReducers, composeEnhancers(applyMiddleware(thunk)))
    

5. 合并 reducer

import { combineReducers } from 'redux'
// 合并 reducer,key:value 形式存在 store 中
const allReducers = combineReducers({
  count: countReducer,
  person: personReducer
})

// 暴露 store 对象
export default createStore(allReducers)

二、react-redux

# 下载 react-redux
npm i react-redux

1. 概念

Provider 提供 store 给子组件。

原理:Provider 利用 context 传递 store 数据。

<Provider store={store}>
   <App />
</Provider>,

connect 连接父组件 provider 提供的 store 数据

connect 就是高阶组件,利用 Provider 中 的 context 获得 store 中的数据,然后 返回一个新组件,属性上添加 store 上的数据。

export default connect(mapStateToProps, mapDispatchToProps)("组件名")
// mapStateToProps 是函数
// mapDispatchToProps 是函数
function mapStateToProps(state){
  return {
      xxxx: state.xxxx
  }
}
function mapDispatchToProps(dispatch){
    return {
        xxx: () => dispatch("创建action的")
    }
}

2. 在react项目中使用

src/index.js

// 引入 Provider,包裹 APP 组件
import { Provider } from "react-redux"
// 引入 store
import store from "./redux/store.js"

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

src/App.js

import React, { Component } from 'react'
import Count from './components/Count'

export default class App extends Component {
  render() {
    return (
      <div>
        {/* 通过react-redux 使用 redux */}
        <Count />
      </div>
    )
  }
}

src/components/Count.jsx

import React, { Component } from 'react'
// 引入connect
import { connect } from "react-redux"
// 引入创建 action 的函数
import { createIncrementAction, createDecrementAction, createAsyncIncrement } from "../store/actions/count"

class NewCount extends Component {
  optionValue = React.createRef();
  increament = () => {
    this.props.jia(+this.optionValue.current.value);
  }
  decreament = () => {
    this.props.jian(+this.optionValue.current.value);
  }
  render() {
    return (
      <div>
        <h2>我是Count组件</h2>
        <p>当前 count 的值:{this.props.count}</p>
        <select name="" id="" ref={this.optionValue}>
          <option value="1">1</option>
          <option value="2">2</option>
          <option value="3">3</option>
        </select>&nbsp;
        <button onClick={this.increament}> + </button>&nbsp;
        <button onClick={this.decreament}> - </button>
      </div>
    )
  }
}
// 使用 connect 
export default connect(
  (state) => ({ count: state.count }),
  {
    jia: createIncrementAction,
    jian: createDecrementAction,
    // jia(num){ dispatch(createIncrementAction(num)) }
  })(NewCount)
posted @ 2021-11-11 15:52  青柠i  阅读(50)  评论(0编辑  收藏  举报