子孙组件如何获取redux中的数据

reduce是redux中用来管理state的地方。通俗一点他就是一个产生数据池的方法。而这个数据池就是可供众多组件共同访问的数据池,不需要组件之间传来传去。

当然reduce也有他自己的弊端,在接受到action指令后,他只能去根据指令来返回一个新的state,而不是直接去修改老的state。这就导致了如果state是一个对象或者是一个数组的时候,处理起来会很麻烦,因为我们不能去动原来的state,只能产生一个新的state。

例如当我们的state是一个数组的时候,这时有一个action指令是要往原先的state数组里添加一项新的数据。如果正常情况下,我们可以接收到这一项新数据之后,直接state.push(item),即可完成添加了。

但是因为reduce中,不允许去修改state,所以这个时候,我们就不得不采取别的方法,可以克隆出一个新数组,然后再去操作新数组。或者是用filter方法,直接产生一个新数组。

这样做真的麻烦,这点个人感觉vuex用起来就爽多了,可以直接去修改state中的数据。

当然事情还没这么简单,试想以下。如果我们这个state非常的庞大,是一个对象,对象里有各种数据类型的属性,有字符串,数值,对象,数组等等。这个时候如果我们接收到一个action,要去操作state中的某一个属性。那将会变得非常非常的麻烦。又不能动原来的state,又去修改state的属性。。。。这真的是头疼。

当然,redux给我们提供了一个方法combineReducers https://www.redux.org.cn/docs/recipes/reducers/UsingCombineReducers.html
这个方法是做什么用的呢?
他支持将多个reduce合并成一个,也就是说,你可以让你的每个reduce只为某一个数据,而不是一个数据的集合。借上文的例子,当state非常庞大的时候,就可以将他拆分成很多个reduce,这样每个reduce只负责他自己的变化,操作方便,简单了很多。combineReducers 方法的作用就是将这些reduc又合并起来,返回一个对象出来。方便你去取数据。

先来看看怎么使用combineReducers方法吧。

/**
 * 包含多个reducer函数的模块
 */
import React from 'react'

export function counter(state = 0, action) {
    switch (action.type) {
        case 'add':
            return state = action.data
        case 'del':
            return state = action.data
        case 'change':
            return state = action.data
        default:
            return state
    }
}

export function newreduce(state = {name:'haha'},action) {
        switch (action.type) {
            case 1:
                return
            default:
                return state
        }
}
这里有两个state,一个是number类型的,一个是对象类型的。
接下来我们在创建store的文件里去合并以下这两个reduce

import {createStore,applyMiddleware,combineReducers} from 'redux'  
import {counter,newreduce} from './redux/reducers'
import thunk from 'redux-thunk'

let mainReduce = combineReducers({counter,newreduce})  这里调用combineReducers方法,传如一个对象,对象的属性就是要合并的reduce

const store = createStore(mainReduce,applyMiddleware(thunk)) 然后将combineReducers方法返回的东西作为reduce传入createStore方法

接下来在组件中打印以下store看看


image.png

可以看到两个reduce已经合并到一起去了,返回了一个新的对象。

下面看一个例子

image.png

上面是一个简单的用redux实现的demo,里面没有复杂的state,这个demo里的state就是一个number。但是借这个简单的例子来讲解以下combineReducers 如何在复杂的state中发挥作用

以下的代码都是基于connect链接之上的,不知道的可以移步上一篇文章https://www.jianshu.com/p/dce005ff1057

在使用了connect链接之后,我们的UI组件就不需要写redux代码了,UI组件中的状态统一由connect生成的容器组件传过来,如下

import React from 'react'
import {Component} from 'react'
import {add,del,addAsync} from './redux/actions'
import Child from "./component";
import PropTypes from 'prop-types'

//引入链接函数
import {connect} from 'react-redux'

class App extends Component {
    constructor(porps) {
        super(porps);
    }
    //声明接收的属性的类型
    static propTypes = {
        data:PropTypes.object.isRequired,
        add:PropTypes.func.isRequired,
        del:PropTypes.func.isRequired,
        addAsync:PropTypes.func.isRequired,
    }

    inputChange = (e) => {
        let count = this.props.data.counter
        count = e.target.value ? e.target.value : null
        this.props.add(count)
    }
    add = () => {
        let count = this.props.data.counter
        count++
        this.props.add(count)
    }
    del = () => {
        let count = this.props.data.counter
        count--
        this.props.del(count)
    }
    ifodd = () => {
        let count = this.props.data.counter
        if (count % 2 !== 0) {
            count++
        }
        this.props.add(count)
    }
    timeadd = () => {
        let count = this.props.data.counter
        this.props.addAsync(count)
    }

    render() {
        console.log(this.props)
        let count = this.props.data.counter
        return (
            <div>
                <h1>click {count} time</h1>
                <input type='number' onChange={this.inputChange} value={count}/>
                <button onClick={this.add}>+</button>
                <button onClick={this.del}>-</button>
                <button onClick={this.ifodd}>increment if odd</button>
                <button onClick={this.timeadd}>increment async</button>
                <Child/>
            </div>
        )
    }
}


//将连接函数暴露出去,连接函数接受两个参数
/**
 * connect
 * 参数1:一个函数,里面返回state
 * 参数2:action
 */
export default connect(
    state=>({data:state}),
    {add,del,addAsync}
)(App)

上述代码主要是展示以下页面结构代码,没参考的意义,重点在下面。

可以看到上述组件中有一个Child的子组件。那如果这个Child组件也想要去修改state的值该怎么办,总不能说app组件接收到的state和方法,再传给子组件吧,如果是这样就违背了集中管理这个初衷了。如果子组件还有他自己的子组件,这样一层一层的传,何必要用redux呢。

子组件获取redux的方法其实很简单,直接把他整成和app组件一样。通过connect将他和store链接起来就行了。这样两个组件都能访问到store。

import React from 'react'
import PropTypes from 'prop-types'
import {add} from "./redux/actions";
import {Component} from 'react'
import {connect} from 'react-redux'

class Child extends Component {
    childrenAdd = () => {
        this.props.add(15)
    }

    render() {
        console.log(this.props, '孙子接受的state')
        return (
            <div>
                <h1 onClick={this.childrenAdd}>孙子组件</h1>
            </div>
        );
    }
}

export default connect(
    state => ({data: state}),
    {add}
)(Child)

我在父组件和子组件中分别都打印了以下props。看看结果


image.png

可以看到,我们给富组件传的data和方法都在,并且data里是包含两个reduce的对象。
而子组件中也是一样,我们传了一个add方法,他接受到了,data他也接收到了。并且值和父组件接收到的是一样的。
现在去操作以下data中的值,看看变化


image.png

我们点击子组件的时候,调用了接收过来的add方法,并且传了15进去。可以看到图中父组件的data中的counter也变成了15。
这就是子孙组件如何获取redux的值的方法

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

推荐阅读更多精彩内容