前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >React 16 - 生态:Redux

React 16 - 生态:Redux

作者头像
Cellinlab
发布2023-05-17 14:20:09
2910
发布2023-05-17 14:20:09
举报
文章被收录于专栏:Cellinlab's Blog

Redux

出现原因

  • Redux:全局只有一个唯一的 Store,负责管理整个应用程序所有的状态
  • 出发点:让组件通信更加容易

(opens new window)

特性

Single Source of Truth

可预测性

纯函数更新 Store

代码语言:javascript
复制
function todo (state = [], action) {
  switch (action.type) {
    case 'ADD_TODO':
      return state.concat([{text: action.text, completed: false}]);
    case 'TOGGLE_TODO':
      return state.map((todo, index) => {
        if (index === action.index) {
          return Object.assign({}, todo, {
            completed: !todo.completed
          });
        }
        return todo;
      });
    default:
      return state;
  }
}

Store

代码语言:javascript
复制
const store = createStore(reducer);
  • getState()
  • dispatch(action)
  • subscribe(listener)

Action

描述行为的数据结构

代码语言:javascript
复制
{
  type: 'ADD_TODO',
  text: 'Learn about actions'
}

Reducer

本质是个函数,接收 state 和 action,返回新的 state

代码语言:javascript
复制
function todoApp (state = initialState, action) {
  switch (action.type) {
    case 'ADD_TODO':
      return Object.assign({}, state, {
        todos: [
          ...state.todos,
          {
            text: action.text,
            completed: false
          }
        ]
      });
    case 'TOGGLE_TODO':
      return Object.assign({}, state, {
        todos: state.todos.map((todo, index) => {
          if (index === action.index) {
            return Object.assign({}, todo, {
              completed: !todo.completed
            });
          }
          return todo;
        })
      });
    default:
      return state;
  }
}

Redux 数据流

combineReducers

代码语言:javascript
复制
export default function todos (state = [], action) {
  switch (action.type) {
    case 'ADD_TODO':
      return [
        ...state,
        {
          text: action.text,
          completed: false
        }
      ];
    default:
      return state;
  }
}
代码语言:javascript
复制
export default function counter (state = 0, action) {
  switch (action.type) {
    case 'INCREMENT':
      return state + 1;
    case 'DECREMENT':
      return state - 1;
    default:
      return state;
  }
}
代码语言:javascript
复制
import { combineReducers } from 'redux';
import todos from './todos';
import counter from './counter';

export default combineReducers({
  todos,
  counter
});

bindActionCreators

写法 1:

代码语言:javascript
复制
function addTodoWithDispatch (text) {
  const action = {
    type: 'ADD_TODO',
    text
  };
  dispatch(action);
}

写法 2:

代码语言:javascript
复制
dispatch(addTodo(text));
dispatch(completeTodo(index));

bindActionCreators 写法:

代码语言:javascript
复制
const boundAddTodo = text => dispatch(addTodo(text));
const boundCompleteTodo = index => dispatch(completeTodo(index));

在 React 中使用 Redux

代码语言:javascript
复制
import { connect } from 'react-redux';

class SidePanel extends Component {}

function mapStateToProps (state) {
  return {
    nextgen: state.nextgen,
    router: state.router
  };
}

function mapDispatchToProps (dispatch) {
  return {
    actions: bindActionCreators({
      ...actions
    }, dispatch),
  };
}

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

复制🤏

connect 工作原理:高阶组件

异步 Action

  • Redux 异步请求
  • 异步 action 不是特殊 action,而是多个同步 action 的组合使用

Redux 中间件

  • 中间件在 dispatcher 中截获 action 做特殊处理
  1. 截获 action
  2. 发出 action

如何组织 Action 和 Reducer

“标准”形式 Redux Action 的问题:

  1. 所有 Action 放一个文件,会无限扩展
  2. Action,Reducer 分开,实现业务逻辑时需要来回切换
  3. 系统中有哪些 Action 不够直观

更好的组织:单个 action 和 reducer 放在同一个文件

  • 新的方法:每个文件一个 Action
  • 易于开发:不用再 action 和 reducer 文件间来回切换
  • 易于维护:每个 action 文件都很小,容易理解
  • 易于测试:每个业务逻辑只需对应一个测试文件
  • 易于理解:文件名就是 action 名字,文件列表就是 action 列表
代码语言:javascript
复制
// counterPlusOne.js
import { COUNTER_PLUS_ONE } from './constants';

export function counterPlusOne() {
  return {
    type: COUNTER_PLUS_ONE
  };
}

export function reducer (state, action) {
  switch (action.type) {
    case COUNTER_PLUS_ONE:
      return {
        ...state,
        counter: state.counter + 1
      };
    default:
      return state;
  }
}

不可变数据 - Immutable Data

为什么采用不可变数据?

  • 性能优化,只需要对比引用
  • 易于调试和跟踪
  • 易于推测

如何操作不可变数据?

原生:{...}, Object.assign()

代码语言:javascript
复制
const state = {
  filter: 'completed',
  todos: [
    'Learn React'
  ]
};
const newState = {
  ...state,
  todos: [
    ...state.todos,
    'Learn Redux'
  ]
};
const newState2 = Object.assign({}, state, {
  todos: [
    ...state.todos,
    'Learn Redux'
  ]
});

immutability-helper,适合更新节点层级较深的复杂情况

代码语言:javascript
复制
import update from 'immutability-helper';
const state = {
  filter: 'completed',
  todos: [
    'Learn React'
  ]
};
const newState = update(state, {
  todos: {
    $push: ['Learn Redux']
  }
});

immer

  • 注意,这种适合简单场景,复杂更新会有性能问题
代码语言:javascript
复制
import produce from 'immer';

const state = {
  filter: 'completed',
  todos: [
    'Learn React'
  ]
};

const newState = produce(state, draftState => {
  draftState.todos.push('Learn Redux');
});
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020/2/4,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Redux
    • 出现原因
      • 特性
        • Store
          • Action
            • Reducer
              • Redux 数据流
                • combineReducers
                  • bindActionCreators
                  • 在 React 中使用 Redux
                    • 异步 Action
                      • Redux 中间件
                        • 如何组织 Action 和 Reducer
                        • 不可变数据 - Immutable Data
                        相关产品与服务
                        消息队列 TDMQ
                        消息队列 TDMQ (Tencent Distributed Message Queue)是腾讯基于 Apache Pulsar 自研的一个云原生消息中间件系列,其中包含兼容Pulsar、RabbitMQ、RocketMQ 等协议的消息队列子产品,得益于其底层计算与存储分离的架构,TDMQ 具备良好的弹性伸缩以及故障恢复能力。
                        领券
                        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档