Skeanmy / Zero2One

学习笔记的仓库
0 stars 1 forks source link

【React】Redux #9

Open Skeanmy opened 4 years ago

Skeanmy commented 4 years ago

Redux

基础

产生原因:单页应用需要管理大量的状态

核心特点:

三大特点:

使用 Object.assign() 新建了一个副本。不能这样使用 Object.assign(state, { visibilityFilter: action.filter }),因为它会改变第一个参数的值。你必须把第一个参数设置为空对象。你也可以开启对ES7提案对象展开运算符的支持, 从而使用 { ...state, ...newState } 达到相同的目的。

工作流程

img

Redux工作流程

store里面有需要的状态,就直接从store中取出来,没有的话会去reducer里面去找

  1. 写代码前先想一下state这个对象的结构,如何才能以最简的形式把应用的 state 用对象描述出来

  2. 用户发出 action,action是数据的唯一来源

    store.dispatch(action);
    • action

    • action函数:作用仅仅是简单的返回一个action,这样容易移植与测试

      // actionCreator.js
      import { CHANGE_INPUT } from './actionTypes';
      // 如果箭头函数直接返回一个对象,必须在对象外面加上括号,否则会报错。
      export const changeInputAction = (value)=>({
       type: CHANGE_INPUT,
       value
      })
  3. 然后,Store 自动调用 Reducer,并且传入两个参数:当前 State 和收到的 Action。 Reducer 会返回新的 State 。

    let nextState = todoApp(previousState, action);
    (previousState, action) => newState
  4. State 一旦有变化,Store 就会调用监听函数。

    // 设置监听函数
    store.subscribe(listener);
    function listerner() {
     let newState = store.getState();
     // component 就是 this
     component.setState(newState);   
    }

小坑

todolist删除时有问题

<List
    bordered
    dataSource={this.props.list}
    renderItem={(item,index)=>(<List.Item onClick={(index)=>{this.props.deleteItem(index)}}>{item}</List.Item>)}
/>

主要是我们的index出现了重新声明的问题。onClick箭头函数接收到的参数是事件对象e不是我们需要的index

<List
    bordered
    dataSource={this.props.list}
    renderItem={(item,index)=>(<List.Item onClick={()=>{this.props.deleteItem(index)}}>{item}</List.Item>)}
/>

创建过程

// index.js
import { createStore } from 'redux'  //  引入createStore方法
import reducer from './reducer'    
const store = createStore(reducer) // 创建数据存储仓库
export default store   //暴露出去

// reducer.js
const defaultState = {}  //默认数据
export default (state = defaultState,action)=>{  //就是一个方法函数
    return state
}

React-redux

image-20200106095737962

redux中间件—redux-thunk

dispatch一个action之后,到达reducer之前,进行一些额外的操作,就需要用到middleware。

你可以利用 Redux middleware 来进行日志记录、创建崩溃报告、调用异步接口或者路由等等。换言之,中间件都是对store.dispatch()的增强

import { applyMiddleware, createStore } from 'redux';
import thunk from 'redux-thunk';
 const store = createStore(
  reducers, 
  applyMiddleware(thunk)
);

redux-thunk最重要的思想,就是可以接受一个返回函数的action creator。如果这个action creator 返回的是一个函数,就执行它,如果不是,就按照原来的next(action)执行。 正因为这个action creator可以返回一个函数,那么就可以在这个函数中执行一些异步的操作。

//异步的action, 由于使用了redux-thunk的thunk中间件,
//所以,在这个action里不用像同步action那样,必须返回一个对象,在这里返回一个方法
//这个方法有一个dispatch的参数,这个dispatch就是store里的dispatch.
export const addAsync = (num = 1) => {
  return (dispatch) => {
    // 当这个方法刚进来的时候,就马上告诉reducer,我要开始获取数据了,
    // reducer接收到这个动作,就会执行相应的操作(把isLoading改为true,看reducer里的代码)
    dispatch({
      type: START_GET_DATA
    });
    // 用setTimeout来模拟获取数据
    setTimeout(() => {
      // 获取数据完成之后,需要dispatch两个action.
      // 一个是把获取到的数据,传到一个动作里(ADD)
      dispatch({
        type: ADD,
        num
      });
      // 这个是用来告诉reducer,我获取数据成功了。reducer接收到这个动作,
      //  就会执行相应的操作(把isLoading改为false,看reducer里的代码)
      dispatch({
        type: GET_DATA_SUCCESS
      });
    }, 2000)
  }
}
Skeanmy commented 4 years ago

@Skeanmy 图片挂了