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

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

查看所有标签

猜你喜欢:

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

黑客渗透

黑客渗透

冰的原点 / 齐鲁电子音像出版社 / 2009-4 / 22.00元

菜鸟起飞,从这里开始!本笔记将透露:渗透、术语、脚本、内网、溢出各种攻击相关的手段和名词,总结、技巧、细节、亮点,不断变化的攻击思想。 ASP、PHP、JSP等不同类型的脚本漏洞,ACCESS、MYSQL、MSSQL、ORACLE等不同类型的数据库缺陷,国内、国外已知和末知的渗透工具······一起来看看 《黑客渗透》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

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

html转js在线工具

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具