美文网首页
子孙组件如何获取redux中的数据

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

作者: 变量只提升声明不提升赋值 | 来源:发表于2021-01-14 16:16 被阅读0次

    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的值的方法

    相关文章

      网友评论

          本文标题:子孙组件如何获取redux中的数据

          本文链接:https://www.haomeiwen.com/subject/psyvaktx.html