• react-redux(1)


    基础

    • Array.prototype.reduce
    //类似的核心思想
    const initState = '';
    const actions = ['a', 'b', 'c'];
    const newState = actions.reduce(
        ( (prevState, action) => prevState + action ),
        initState
    );
    
    //action: actions;
    //state: initState,newState;
    //reducer: (prevState, action) => prevState + action //计算
    

    Action

    • 描述有什么事情发生了;
    {
      type: 'ADD_TODO',
      text: 'Build Redux app'
    }
    
    • 改变State只能通过actions, 使用store.dispatch()。并且,每一个action都必须是Javascript Plain Object;
    • 为保证状态保存、回放、Undo 之类的功能可以被实现, action必须是可以被序列化的因此,不能包含如函数调用这样的不可序列化字段;
    • type是必须要有的字符串属性; 建议文档;
    • 好的结构中应该每次action传需要的数据而不是整个
    {
      type: SET_VISIBILITY_FILTER,
      filter: SHOW_COMPLETED
    }
    

    Action Creator

    • 事实上,创建action对象更多地是通过一个创建函数;
    function addTodo(text) {
      return {
        type: ADD_TODO,
        text
      };
    }
    //触发
    dispatch(addTodo(text));
    
    • dispatch可以直接来自store.dispatch;
    handleClick() {
      // Works! (but you need to grab store somehow)
      store.dispatch(addTodo('Fix the issue'));
    }`
    
    • react-redux中可以通过connect(mapStateToProps,mapDispatchToProps)(Counter);
      • mapStateToProps函数通过返回一个映射对象selector,指定了 Store/State属性映射到React Componentthis.props的情况;
    class AddTodo extends Component {
      handleClick() {
        // Works!
        this.props.dispatch(addTodo('Fix the issue'));
      }
      ....
    }
    
     //将dispatch和state放入props
    export default connect(select)(AddTodo);
    
    • 或者结合bindActionCreators(actionCreators, dispatch);
    import * as CounterActions from '../actions/counter';
    
    function mapStateToProps(state) {
      return {
        counter: state.counter
      };
    }
    
    function mapDispatchToProps(dispatch) {
      return bindActionCreators(CounterActions, dispatch);
    }
    
    export default connect(mapStateToProps, mapDispatchToProps)(Counter);  //可以直接添加actionCreators
    
    //调用
    <button onClick={this.props.addTodo}/>add</button>
    
    

    Reducers

    • 描述事情发生后state如何改变;

    更新成员

    • 为了确保State的消费者在判断数据是否变化时,只要简单地进行引用比较避免Deep Equal的遍历,需要确保State中每个节点都是不可改变的;

    • Reducer中更新State成员需要

    • 增加

    //对象
    let counters = {
        faves: 0,
        forward: 20,
    }
    // this creates a brand new copy overwriting just that key
    counters = {...counters, faves: counters.faves + 1}
    
    //数组;  调换顺序,可以改变增加的位置;
    
    let todos = [
        { id: 1, text: 'have lunch'}
    ]
    todos = [...todos, { id: 2, text: 'buy a cup of coffee'} ]
    
    • 删除
    //数组
    let users = [...];
    users = users.filter(user=> user.id !== find.id)
    
    • 由于更新数据的差异:如对于数组型react:state操作后,会同时更新操作位置之后的数据;而redux则只会更新操作位置的数据;

    同步执行

    • Reducer的执行是同步的;
    • 在给定initState以及一系列的actions,都应该得到相同的newState;

    分割reduce

    • Reduceraction.type是多对多的关系;
    export default function counter(state = 0, action) {
      switch (action.type) {
      case INCREMENT_COUNTER:
        return state + 1;
      case DECREMENT_COUNTER:
        return state - 1;
      default:
        return state;
      }
    }
    
    • 在程序变多时可以使用combineReducers({field1: reducerForField1,....})来管理
      • 每个reducerForField1将仅仅获得State.field1的值,而看不到State下的其他字段的内容;
      • 响应的返回结果也会被合并到对应的State字段中;
    import { combineReducers } from 'redux';
    
    const todoAppReducer = combineReducers({
      visibilityFilter: visibilityFilterReducer
      todos: todosReducer
    });
    
    //
    visibilityFilterReducer 仅仅负责处理 State.visibilityFilter 字段的状态
    
    • 注意使用combineReducers的前提是,每一个被组合的Reducer仅仅和State的一部分数据相关;
    • 如果需要消费其他State字段,那还是需要在大switch中为特定处理函数传入整个State;
    function todoAppReducer(state = initialState, action) {
      switch (action.type) {
      case FAVE_ALL_ITEMS:
        return Object.assign({}, state, faveThemAll(state));
      default:
        return state;
      }
    }
    
    

    Store

    • 维护应用程序状态的对象;
    • 构造Store对象,仅需要提供一个Reducer函数;
    import { combineReducers, createStore } from 'redux';
    import * as reducers from './reducers';
    
    const todoAppReducer = combineReducers(reducers);
    const store = createStore(todoAppReducer);  // Line 5
    
    store.dispatch({type: 'ADD_TODO', text: 'Build Redux app'});
    
    • 可以在createStore的时候为Store指定一个初始状态;
    const store = createStore(reducers, window.STATE_FROM_SERVER);
    

    方法

    • store.getState(): 获取最近的内部状态对象;
    • store.dispatch(action): 将一个action对象发送给reducer;
    • store.subscribe(listener):订阅状态的变化;并不推荐使用, 可以搭配Observable模式的程序,react中不建议;

    Provider Component

    • 通过Provider Component来设定connect从哪里获得store对象;
    React.render(
      <Provider store={store}>
        {() => <MyRootComponent />}   //react 0.14: <MyRootComponent />
      </Provider>,
      rootEl
    );
    

    主要流程

    • 设置redecers,分片的话使用redux: combineReducers;
    • 创建store,使用redux: createStore,传入reducers;
    • 在特定的组件/顶层组件绑定状态和dispatch,使用react-redux: connet,传入状态映射selector;
    • store关联到绑定后的特定/顶层组件,使用react-resuc: Provider;
    • 设置actions,并在组件想要调用的地方触发this.props.dispatch(),自动更新state;

    其他

    • 在绑定组件时使用redux: bindActionCreators,connect传入第二参数,直接将dispatch(actions)传入组件ptops; //注意此时action则必须是Action Creator;
    • 在创建store时使用redux: applyMiddleware先传入中间件,再创建
    import { createStore, applyMiddleware } from 'redux';
    import thunk from 'redux-thunk';
    import reducer from '../reducers';
    
    const createStoreWithMiddleware = applyMiddleware(
      thunk
    )(createStore);
    
    export default function configureStore(initialState) {
      const store = createStoreWithMiddleware(reducer, initialState);
      return store;
    }
    //
    const store = configureStore();
    
    
  • 相关阅读:
    第五百五十二天 how can I 坚持
    第五百五十一天 how can I 坚持
    第五百五十天 how can I 坚持
    第五百四十七、八、九 how can I 坚持
    第五百四十六天 how can I 坚持
    第五百四十五天 how can I 坚持
    第五百四十四 how can I 坚持
    第五百四十一、二、三天 how can I 坚持
    第五百四十天 how can I 坚持
    MySql
  • 原文地址:https://www.cnblogs.com/jinkspeng/p/4820788.html
Copyright © 2020-2023  润新知