# Redux 笔记

# 使用 Redux

基本工作流程:

  • ReactComponents - 借书人
  • ActionCreators- 借书语句发布器
  • store - 图书馆
  • Reducers - 馆藏记录

首先ReactComponents想要获取store里面的哪一条数据,通过ActionCreators发布事件,想要获取哪一本书书的数据,然后storeReducers去查找数据,最后返回给组件。修改流程也基本相似。

基本使用案例

首先安装redux

$ npm install redux

然后在src下创建store目录,依次创建index.jsreducer.js

书写reducer文件: 相当于图书馆的记录册,里面定义stateaction的记录

// 定义默认state
const defaultState = {
  inputValue:'',
  list:[]
}
export default (state = defaultState,action){
  // 定义action
  return state
}

书写入口文件

import { createState } from "redux";
import reducer from "./reducer";

// 第二个参数是调试redux-tools传递的默认参数
const store = createState(reducer, window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__());
export default store;

准备好之后在需要使用到redux的文件中引入并修改数据

Example

import store from './store'
export default class Test extends Component{
  constructor(props){
    super(props)
    // store.getState() 获取state数据
    this.state = store.getState()
    this.changeInputValue = this.changeInputValue.bind(this)
  }
  render(){
    return (
    ...
    )
  }
}

假设我要改变inputValue并且更新当前的state

  1. 定义action

    在方法定义时定义action,然后通过storedispatch这个 API 去触发更新

    action一遍指定typevalue 就当做vuex里面的mutation

    changeInputValue(e){
      const action = {
        type:'change_input_value',
        value:e.target.value
      }
      store.dispatch(e)
    }
    
  2. 书写reducer

    判断当前的action的类型,然后在旧数据基础上做一层深拷贝,根据action改变拷贝的数据然后返回,提交给store,之后store会自动讲新数据更新

export default (state = defaultState, action) => {
  if (action.type === "change_input_value") {
    const newState = JSON.parse(JSON.stringlfy(state));
    newState.inputValue = action.value;
    return newState;
  }
};
  1. 拆分actionstypes

    你会发现当action越来越多,reducer这个文件就会越撑越大。这里可以继续拆分模块

创建actionTypes

export const CHANGE_INPUT_VALUE = 'change_inpu_value'
...

创建actionCreators

import * as types from "./actionTypes";

export const getChangeInputAction = value => ({
  type: types.CHNAGE_INPUT_VALUE,
  value
});

最后使用到action

handleChangeInputValue(e){
  const action = actions.getChangeInputAction(e.target.value)
  store.dispatch(action)
}

# 结合 charles mock 本地数据

# 使用 redux-thunk 改造 action

原生的action只能封装为一个对象,如果我们想要去封装一些异步的操作和业务逻辑就没法完成,这时候需要借助到redux中间件这个概念。

中间件reduxstoreaction之间的桥梁,它可以在dispatch里面传入异步函数

使用redux-thunk方法

  1. 安装并在store的入口文件引入,然后按照官网 (opens new window)配置方式配置

    import thunk from "redux-thunk";
    import { createStore, applyMiddleware, compose } from "redux";
    import reducer from "./reducer";
    
    const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__
      ? window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({})
      : compose;
    const enhancer = composeEnhancers(applyMiddleware(thunk));
    const store = createStore(reducer, enhancer);
    export default store;
    
  2. 接下来就可以封装包含异步操作的action

    export const testAction = () => {
      // 返回函数时会带上dispatch这个参数
      return dispatch => {
        // 异步操作 或者调用其他action 再dispatch
      };
    };
    

# React-redux

react-redux简化了使用reduxstore和 dispatchaction的使用,类似于vuex的 map 语法糖

相关知识点

react-redux将组件分为

  • UI 组件 (只负责 UI 呈现,不包含业务逻辑),不使用state,所有数据均由props提供
  • 容器组件 (管理数据和业务逻辑 不负责 UI),带有state

connect方法: 将UI组件生成容器组件

import { connect } from "react-redux";
export default connect(mapStateToProps, mapDispatchToProps)(Todolist);

阮一峰: connect方法接受两个参数:mapStateToPropsmapDispatchToProps。它们定义了 UI 组件的业务逻辑。前者负责输入逻辑,即将state映射到 UI 组件的参数(props),后者负责输出逻辑,即将用户对 UI 组件的操作映射成 Action。

  • mapStateToProps

    建立一个从(外部的)state对象到(UI 组件的)props对象的映射关系。

    const mapStateToProps = (state, ownProps) => {
      return {
        todos: state.todo
      };
    };
    
  • mapDispatchToProps

    用来建立 UI 组件的参数到store.dispatch方法的映射。也就是说,它定义了哪些用户的操作应该当作 Action,传给 Store。

    const mapDispatchToProps = (dispatch,ownProps)=>{
      return {
        handleClick(){
          const action = {
            ...
          }
          dispatch(action)
        }
      }
    }
    

安装和使用

$ npm install react-redux
  1. react的入口文件中配置provider,搭建组件之间和store的联系
import {Provider} from 'react-redux'
import Todlolist from './Todolist'
import store from './store'
...

// 容组件放进容器 bing'jian
const App = (
<Provider store={store}>
  <<Todolist></Todolist>
  </Provider>
)

ReactDom.render(App,document.getElementById('root'))

  1. 组件连接

    import react, {Component} from 'react'
    import {connect} from 'react-redux'
    
    class Todolist extends Component{
      render(
      ..
      )
    }
    
    // 定义State映射关系和dispatch映射关系
    const mapStateToProps = (state)=>{
      return {
        inputValue: state.inputValue
        ....
      }
    }
    
    const mapDispatchToProps = (dispatch)=>{
      return {
        hanldeClick(){
          ...
          const action = {
    
          }
          dispatch)(action)
        }
      }
    }
    

// 导出连接上 store 的组件 export default connenct(mapStateToProps,mapDispatchProps)(Todolist)


3. 使用`state`或者`dispatch`

```js
this.props.inputValue;
this.props.handleClick;
Last update: 7/20/2021, 8:53:54 AM