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中一樣實用,這裏就不貼相關代碼了

相關文章
相關標籤/搜索