React中Redux与Ref 联合使用时值得关注的一个问题

相信用过React(或者React-Native,如下简称RN)的朋友对ReduxRef这两个概念都很熟悉,前者是开发React或RN比较经常使用的数据管理框架,固然不单单限于React或RN;后者是React提供的专门用于直接操做dom的接口,也能够用来直接调用组件内的方法,固然用法也不单单限于这两个。额...彷佛有点偏了,由于这两个概念不是本文的重点因此不加赘述,有兴趣的朋友能够到官方文档里一睹庐山真面目。话很少说,下面开始进入正题吧,Let's Go!react

接下来我会用一个简单的demo来演示这个问题是如何发生以及如何解决的:
首先新建一个Addition组件,该组件用于显示一个数值,而且能够经过调用Addition组件的addHandler对这个数值进行+1,主要代码以下:git

class Addition extends Component {
    constructor(props) {
        super(props);
        this.state = {
            value: 0
        }
    }

    addHandler = () => {
        this.setState({
            value: this.state.value + 1
        })
    };

    render() {
        return (
            <div>
                <p>{this.state.value}</p>
            </div>
        )
    }
}

export default Addition

可是咱们并无看到在这个组件里调用了这个方法,因此有经验的朋友可能会猜到这个方法是在其父组件里经过ref直接调用了这个addHandler方法,代码以下:github

class App extends Component {
    clickHandler = () => {
        this.refs.addition.addHandler();
    };

    render() {
        return (
            <Provider store={store}>
                <div className="App">
                    <Addition ref='addition'/>
                    <button onClick={this.clickHandler}>加加加</button>
                </div>
            </Provider>
        );
    }
}

export default App;

这样写运行起来没有任何问题:redux

clipboard.png

经过点击‘加加加’实现对数值的+1处理。api

可是假若有这样一个需求:须要在 Addition中读取Redux中的一个数据(固然这个例子没有体现出来),那么就须要connect一下了:
export default connect(mapStateToProps, mapDispatchToProps)(Addition)

嗯,看起来很完美,开开心心得从新运行下,点击,而后....boom( ⊙ o ⊙ )啊!报错了,app

clipboard.png

不科学啊,说到这里相信你们都能猜出来事connect事后致使的问题,因此去官方文档翻箱倒柜一下connect([mapStateToProps], [mapDispatchToProps], [mergeProps], [options])
果不其然,原来connect参数有4个,因此多是遗漏了某个参数吧,因此继续翻...
而后看到这样一段话:框架

[withRef] (Boolean): If true, stores a ref to the wrapped component instance and makes it available via getWrappedInstance() method. Default value: false

简单理解下,就是说connect事后export出去的不是组件自己,而是通过包装处理的组件,官方称之为wrapped component,因此默认是不将ref存储到这个包装对象里的(Default value: false),所以只有将withRef这个参数置为true,那么Redux就会将ref存储到这个包装对象里以供使用了,而且请注意下via getWrappedInstance() method这段话,即使咱们将withRef置为true但没有经过getWrappedInstance()得到原对象的ref(reference)也是不行的。因此说道这里你们也知道解决方案是什么了:dom

1)connect导出 Addition组件时候添加 withRef参数:
export default connect(mapStateToProps, mapDispatchToProps, null, {withRef: true})(Addition)

2)调用addHandler方法前使用getWrappedInstance()得到原对象的refthis.refs.addition.getWrappedInstance().addHandler()ide

而后从新运行,bingo,一切正常!!!!this

源码 在这 ,有兴趣的朋友能够拉取代码尝试下。

实测,该方法在React-Native中一样实用,这里就不贴相关代码了

相关文章
相关标签/搜索