redux以及react-redux

一.基本概念

redux有三个基本的概念:action reducer store

1.action:

是把数据传到store的有效载荷,它是store数据的唯一来源,用法是通过store.dispatch()方法将action传到store

2.reducer:

action描述了一些事件发生的事实,但是并没有明确指出state如何变化的,所以reducer用来指出如何更新,reducer是一个纯函数
不要在reducer里面做这些操作

  • 修改传入参数;
  • 执行有副作用的操作,如 API 请求和路由跳转;
  • 调用非纯函数,如 Date.now() 或 Math.random()
总之action就像是领导,告诉reducer该干什么活,reducer再对store进行处理更新
3.store: 一个应用只有一个store

store有如下几个职责

  • 维持应用的state
  • 提供getState()方法获取state
  • 提供dispatch方法更新state
  • 通过 subscribe(listener) 注册监听器
总之store提供了一些方法将action和reducer联系在一起

二.详细介绍

1.action:action是一个普通的对象,redux规定action里面的type字符串类型字段用来代表执行的动作,还可以存放一些其他的想要操作的字段
{
   type: 'ADD_TODO',
   text:'',
}

但是实际上我们需要一个函数来为我们创建Action,例如一个addTodo函数

const addTodo = text => ({
   type: 'ADD_TODO',
   text,
})
2.reducer:reducer是一个纯函数

当它被Redux调用的时候会为他传递两个参数state和action,reducer会根据action的type来对旧的state进行更新,返回新的state

const todos = (state = [], action) => {
    switch (action.type) {
      case 'ADD_TODO':
        return [
          ...state,
          {
            id: action.id,
            text: action.text,
            str: action.str,
            completed: false
          }
        ]
      case 'TOGGLE_TODO':
        return state.map(todo =>
          (todo.id === action.id)
            ? {...todo, completed: !todo.completed}
            : todo
        )
      default:
        return state
    }
  }

注意reducer函数里面的几点:

  • 不要修改state
  • 在 default 情况下返回旧的 state
  • 如果没有旧的State,就返回一个initialState
    如果在default或没有传入旧State的情况下不返回旧的State或initialState。。。那么当前的State会被重置为undefined!!
    真正开发项目的时候State会涉及很多功能,在一个Reducer处理所有逻辑会非常混乱,,所以需要拆分成多个小Reducer,每个Reducer只处理它管理的那部分State数据。然后在由一个主rootReducers来专门管理这些小Reducer。
3.store

createStore有两个参数Reducer 和 initialState

let store = createStore(rootReducers, initialState);

store有四个方法。

getState: 获取应用当前State。
subscribe:添加一个变化监听器。
dispatch:分发 action。修改State。
replaceReducer:替换 store 当前用来处理 state 的 reducer。
常用的是dispatch,它是修改state的唯一途径

// action
const addTodo = text = ({
   type: 'ADD_TODO',
   text,
})
store.dispatch(addTodo('textval'))

二.react-redux

redux是独立的,它与react没有任何关系,React-Redux是官方提供的一个库,用来结合redux和react的模块。

根据官方的todolist,补充一下react组件类型的知识点

React redux设计思想是根据容器组件和展示组件分离的思想开发


两者区别

通俗的说,如果你需要state和生命周期,那么你就要用class容器组件
React-Redux提供了两个接口Provider、connect。

Provider

provider是react的一个组件,它的作用是保存store给子组件的connect使用,Provider来 魔法般的让所有容器组件都可以访问 store,而不必显示地传递它。只需要在渲染根组件时使用即可,它的唯一功能就是传入store对象

1.通过getChildContext方法把store保存到context里。
2.后面connect中会通过context读取store。
它看起来是这个样子

import React from 'react'
import { render } from 'react-dom'
import { Provider } from 'react-redux'
import { createStore } from 'redux'
import todoApp from './reducers'
import App from './components/App'

let store = createStore(todoApp)

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

一部分核心源码

getChildContext() {
  return { store: this.store }
}

constructor(props, context) {
  super(props, context)
  this.store = props.store
}
connect

connect会将state,dispatch转换成props传递给子组件,一般此代码写在container容器组件里面,里面的参数传其中的几个都可以

import { connect } from 'react-redux'
import { toggleTodo } from '../actions'
import TodoList from '../components/TodoList'

const getVisibleTodos = (todos, filter) => {
  switch (filter) {
    case 'SHOW_COMPLETED':
      return todos.filter(t => t.completed)
    case 'SHOW_ACTIVE':
      return todos.filter(t => !t.completed)
    case 'SHOW_ALL':
    default:
      return todos
  }
}

const mapStateToProps = state => ({
  todos: getVisibleTodos(state.todos, state.visibilityFilter)
})

const mapDispatchToProps = dispatch => ({
  toggleTodo: id => dispatch(toggleTodo(id))
})

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(TodoList)

这个方法会使用黑魔法把state,dispatch转换成props传递给react组件

mapStateToProps:

mapStateToProps是一个普通函数,当它被connect 调用的时候,会为它传递一个参数state,它主要的事情就是 返回需要传递给子组件的state,然后connect会拿到返回数据写到组件中,然后组件就可以通过props读取数据了~

const mapStateToProps = state => ({
  todos: getVisibleTodos(state.todos, state.visibilityFilter)
})
mapDispatchToProps:

与mapStateToProps很像,也是一个函数,他被connect调用的时候会被传递一个dispatch 参数,它负责返回一个dispatchProps

const mapDispatchToProps = dispatch => ({
  toggleTodo: id => dispatch(toggleTodo(id))
})

connect收到数据之后,会把它放在react组件上,然后子组件就可以通过props拿到 toggleTodo去使用,每当调用这个方法就会更新state

this.props.toggleTodo('hello');
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 162,306评论 4 370
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,657评论 2 307
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 111,928评论 0 254
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,688评论 0 220
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 53,105评论 3 295
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 41,024评论 1 225
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,159评论 2 318
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,937评论 0 212
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,689评论 1 250
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,851评论 2 254
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,325评论 1 265
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,651评论 3 263
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,364评论 3 244
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,192评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,985评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 36,154评论 2 285
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,955评论 2 279

推荐阅读更多精彩内容