Redux 学习总结 (React)

栏目: 服务器 · 发布时间: 5年前

内容简介:在 React 的学习和开发中,如果 state (状态)变得复杂时(例如一个状态需要能够在多个 view 中使用和更新),使用 Redux 可以有效地管理 state,使 state tree 结构清晰,方便状态的更新和使用。当然,Redux 和 React 并没有什么关系。Redux 支持 React、Angular、Ember、jQuery 甚至纯 JavaScript。只是对我来说目前主要需要在 React 中使用,所以在这里和 React 联系起来便于理解记忆。

在 React 的学习和开发中,如果 state (状态)变得复杂时(例如一个状态需要能够在多个 view 中使用和更新),使用 Redux 可以有效地管理 state,使 state tree 结构清晰,方便状态的更新和使用。

当然,Redux 和 React 并没有什么关系。Redux 支持 React、Angular、Ember、jQuery 甚至纯 JavaScript。只是对我来说目前主要需要在 React 中使用,所以在这里和 React 联系起来便于理解记忆。

数据流

Redux 学习总结 (React) Redux 学习总结 (React)

Action

只是描述 state (状态)更新的动作,即“发生了什么”,并不更新 state。

const ADD_TODO = 'ADD_TODO'

{
  type: ADD_TODO,
  text: 'Build my first Redux app'
}
  • type:必填,表示将要执行的动作,通常会被定义成字符串常量,尤其是大型项目。
  • 除了 type 外的其他字段:可选,自定义,通常可传相关参数。例如上面例子中的 text。

Action 创建函数

简单返回一个 Action:

function addTodo(text) {
  return {
    type: ADD_TODO,
    text
  }
}

dispatch Action:

dispatch(addTodo(text))
// 或者创建一个 被绑定的 action 创建函数 来自动 dispatch
const boundAddTodo = text => dispatch(addTodo(text))
boundAddTodo(text)

帮助生成 Action 创建函数的库(对减少样板代码有帮助):

Reducer

说明在发起 action 后 state 应该如何更新。

是一个纯函数:只要传入参数相同,返回计算得到的下一个 state 就一定相同。

(previousState, action) => newState

注意,不能在 reducer 中执行的操作:

  • 修改传入的参数
  • 执行有副作用的操作,如 API 请求和路由跳转
  • 调用非纯函数,如 Date.now() 或 Math.random()
import { combineReducers } from 'redux'
import {
  ADD_TODO,
  TOGGLE_TODO,
  SET_VISIBILITY_FILTER,
  VisibilityFilters
} from './actions'
const { SHOW_ALL } = VisibilityFilters

function visibilityFilter(state = SHOW_ALL, action) {
  switch (action.type) {
    case SET_VISIBILITY_FILTER:
      return action.filter
    default:
      return state
  }
}

function todos(state = [], action) {
  switch (action.type) {
    case ADD_TODO:
      return [
        ...state,
        {
          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
  }
}

const todoApp = combineReducers({
  visibilityFilter,
  todos
})

export default todoApp

Store

Redux 应用只有一个单一的 store。

  • 维持应用的 state;
  • 提供 getState() 方法获取 state;
  • 提供 dispatch(action) 方法更新 state;
  • 通过 subscribe(listener) 注册监听器;
  • 通过 subscribe(listener) 返回的函数注销监听器。
import { createStore } from 'redux'
import todoApp from './reducers'
let store = createStore(
  todoApp,
  [preloadedState], // 可选,state 初始状态
  enhancer
)
import { createStore, combineReducers, applyMiddleware, compose } from 'redux'
import thunk from 'redux-thunk'
import DevTools from './containers/DevTools'
import reducer from '../reducers/index'

export default function configureStore() {
  const store = createStore(
    reducer,
    compose(
      applyMiddleware(thunk),
      DevTools.instrument()
    )
  );
  return store;
}

react-redux

connect() 方法( mapStateToPropsmapDispatchToProps

替代 store.subscribe() ,从 Redux state 树中读取部分数据,并通过 props 提供给要渲染的组件。

import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import * as actions from './actions';

class App extends Component {
  handleAddTodo = () => {
    const { actions } = this.props;
    actions.addTodo('Create a new todo');
  }
  render() {
    const { todos } = this.props;
    return (
      <div>
        <Button onClick={this.handleAddTodo}>+</Button>
        <ul>
          {todos.map(todo => (
            <Todo key={todo.id} {...todo} />
          ))}
        </ul>
      </div>
    );
  }
}

function mapStateToProps(state) {
  return {
    todos: state.todos
  };
}

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

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

Provider 组件

import React from 'react'
import { render } from 'react-dom'
import { Provider } from 'react-redux'
import configureStore from './store/configureStore'
import App from './components/App'

render(
  <Provider store={configureStore()}>
    <App />
  </Provider>,
  document.getElementById('root')

API 请求

一般情况下,每个 API 请求都需要 dispatch 至少三种 action:

  • 通知 reducer 请求开始的 action { type: 'FETCH_POSTS_REQUEST' }
    reducer 可能会 {...state, isFetching: true}
  • 一种通知 reducer 请求成功的 action { type: 'FETCH_POSTS_SUCCESS', response: { ... } }
    reducer 可能会 {...state, isFetching: false, data: action.response}
  • 一种通知 reducer 请求失败的 action { type: 'FETCH_POSTS_FAILURE', error: 'Oops' }
    reducer 可能会 {...state, isFetching: false, error: action.error}

使用 middleware 中间件实现网络请求:

redux-thunk

通过使用指定的 middleware,action 创建函数除了返回 action 对象外还可以返回函数。这时,这个 action 创建函数就成为了 thunk。

路由跳转( react-router

参考资料:

  1. Redux 中文文档
  2. React Native Training

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

CSS 3实战

CSS 3实战

成林 / 机械工业出版社 / 2011-5 / 69.00元

全书一共分为9章,首先从宏观上介绍了CSS 3技术的最新发展现状、新特性,以及现有的主流浏览器对这些新特性的支持情况;然后详细讲解了CSS 3的选择器、文本特性、颜色特性、弹性布局、边框和背景特性、盒模型、UI设计、多列布局、圆角和阴影、渐变、变形、转换、动画、投影、开放字体、设备类型、语音样式等重要的理论知识,这部分内容是本书的基础和核心。不仅每个知识点都配有丰富的、精心设计的实战案例,而且详细......一起来看看 《CSS 3实战》 这本书的介绍吧!

html转js在线工具
html转js在线工具

html转js在线工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具