[React]Redux初探

来源:
Redux入门教程-阮一峰
文档:
Redux中文文档

基本概念

Store

Store是Redux保存数据的地方,一个应用只能有一个Store;
生成:

import {createStore} from 'redux'
const store=createStore(fn);

使用createStore()来接收另一个函数作为参数生成Store对象,这个参数是Reducer;它也可以接收另一个参数,这个参数将会表示State的最初状态;

let store = createStore(todoApp, window.STATE_FROM_SERVER)

在上面的例子中,window.STATE_FROM_SERVER将会是状态初始值,如果提供了这个参数,Reducer的默认初始值将会被覆盖。

State

State是Store的一份快照,它是在一个时刻的时候的Store.
当前时刻的State使用store.getState()获得

import {createStore} from 'redux'
const store=createStore(fn);
const state=store.getState();

State与视图层View绑定,两者相关。

Action

State的变化由View导致,Action是View发出的通知,表示使State发生变化。
Action是一个对象,其中只有type属性是必须设置的。

const action={
    type:"ADD",
    payload:"Learn Redux",
}

上述Action的名称为type属性,携带的信息为payload的值。

Action Create

Action Creator用来生成Action

const todoSomething="ADD";
function addTodo(payload){
    return {
        type:todoSomething,
        payload
}
}
const action=addTodo("Learn Redux")

事实上,这里的action和上一个例子的action相同的。
addTodo函数为一个Action Creator

store.dispatch()

store.dispatch()是View发出Action的唯一方法;

import {createStore} from 'redux'
const store=createStore(fn);

store.dispatch({
    type:"ADD",
    payload:"Learn Redux"
})

在上面的例子里,store.dispatch()接收了一个Action作为参数。
使用store.Create后,可以将代码改写为:

store.dispatch(addTodo('Learn Redux'));

Reducer

Store接收到Action之后,将会使用Reducer来使State发生变化,进而影响到View。
Reducer是一个函数,它接收Action和State作为参数,返回一个新的State

const reducer=function (state,action){
    //...
    return newState;
}

我们可能会需要一个State的初始状态,这个时候,我们可以使用:

const defaultState=0;
const reducer=(state=defaultState,action)=>{
    switch(action.type){
        case "ADD":
            return state+action.payload;
        default:
            return state;    
}
};
const state=reducer(1,{
    type:"ADD",
    payload:2
})

在上面的代码中,reducer在接收到名称为ADD的Action后,将State的值进行处理并返回相加的值。

在实际运行时,Reducer不需要手动调用,store.dispatch()将会自动触发Reducer执行。
为了使得Reducer自动执行,Store需要知道Reducer,所以在Store生成时,将Reducer作为参数传入createStore();
Reducer必须是一个纯函数,所以请使用以下写法:

//State是一个对象时
function reducer(state,action){
    return Object.assign({},state,{thingToChange});
    //or
    return {...state,...newState};
}
//State是一个数组时
function reducer(state,action){
    return[...state,newItem];
}

Object.assign()将会将对象进行合并,关于该函数的详细知识,请看这里。
值得注意的是,在任何时候State都不应该发生改变,即一个时刻对应一个新的State,对应一个新的View,不应该试图对State进行改变。

reducer的拆分

在state变得巨大的时候,Reducer也会随之变大,可以使用combineReducers方法将不同的Reducer子函数进行合并为一个大函数。

import { combineReducers } from 'redux';

const chatReducer = combineReducers({
  chatLog,
  statusMessage,
  userName
})

export default todoApp;

这种写法有一个前提:State的属性名字需要与Reducer的子函数同名,否则采用以下写法:

const reducer = combineReducers({
  a: doSomethingWithA,
  b: processB,
  c: c
})

// 等同于
function reducer(state = {}, action) {
  return {
    a: doSomethingWithA(state.a, action),
    b: processB(state.b, action),
    c: c(state.c, action)
  }
}

store.subscribe()

import { createStore } from 'redux';
const store = createStore(reducer);

store.subscribe(listener);

Store使用该方法设置监听函数,在State发生变化的时候将会自动执行。
在通常情况下,要将View的更新函数作为在listenr中,对于react,这将会是对state的更新做出反应的函数,如setState()或者是render()
store.subscribe()将会返回一个函数,调用这个函数就可以解除监听。

一个实例

这个实例中,希望实现一个面包屑,这个面包屑的显示将会随着路由的变化发生变化。

//store.js
import {createStore} from 'redux'
import reducer from '../reducer'
const default={
    menuName:"首页"
}
//创建store,初始值为default
const configStore=createStore(reducer,default);
//reducer.js
import {type} from '../action'
//创建Reducer:Data,如果Action的type是"SWITCH_MENU",将会对menuName进行修改
const Data=(state,action)=>{
    switch(action.type){
        case "SWITCH_MENU":
            return {
                ...state,
                menuName:action.menuName
            };
        default:
            return {...state};
}
};
export default Data;
//action
export function switchMenu(menuName){
       return{
            type:"SWITCH_MENU",
            menuName
}
}

以上,redux的基本功能已经完成,store存储数据,reducer将会对action进行响应。如何

你可能感兴趣的:([React]Redux初探)