2017-03-14 40 views
2

當實現像Redux或MobX這樣的狀態容器時,你的狀態和事件通常會移動到一個單獨的類或不再能讀取refs的對象。反應:如何從Redux/Flux操作訪問組件參考?

例如,在一個正常的組成部分:

import Alert from Alert.js; 

class Dummy extends React.Component { 
    constructor(props) { 
    super(props); 

    this.state = { clicked: false } 
    } 

    handleClick() { 
    fetch('api').then(function(){ 
     this.setState({ clicked: true }); 
     this._alert.show('Cool response!'); 
    }); 
    } 

    render() { 
    return (
     <div> 
     <Alert ref={a => this._alert = a} /> 
     <Button onClick={this.handleClick}/> 
     </div> 
    ) 
    } 
} 

如果我按一下按鈕,一旦服務器請求完成後,狀態更新,並觸發警報。像這樣使用ref在一些模式和警報庫中很常見。

現在,在Redux(或任何Flux實現)中,fetch()將存在於一個獨立文件中的動作中,該文件無法訪問this._alert

在不重寫外部「警報」庫的情況下維護功能的最佳方式是什麼?

+0

在你的行動中,你可以返回一個承諾I.E. API調用,你可以這樣做: 'this.props.fetchSomething.then(()=> this._alert.show(「反應冷淡!」)',你只需要確保你正在返回的承諾 – finalfreq

+0

返回Promise是一個好主意,但您需要使用一些中間件來允許您的操作返回承諾,如'redux-promise-middleware'或類似的東西 – disstruct

回答

3

作爲一個說明,我從您的文章就來了:https://dannyherran.com/2017/03/react-redux-mobx-takeaways/

這是從一開始就錯了。不應該在組件之間共享參考,因爲它們將它們耦合在一起。組件的設計應完全相互分離,並根據給定的狀態作出反應。

問題是,ref告訴你關於組件本身的狀態,你不知道它是否掛載,你不知道它是否存在,所以你玩的東西易變。

讓我們分離的一切,並充分利用的反應,和/終極版得當,所有代碼應該以這種方式組織的力量:

1.減速機:

減速將保持戒備的顯示狀態。 現在,整個應用程序中的任何組件都可以訪問它,獨立的refs,因此組件實際是否存在並不重要。

const DummyPageReducer = function(state, action) 
{ 
    if (state === undefined) 
    { 
     state = 
     { 
      alertShow: false 
     }; 
    } 

    switch(action.type) 
    { 
     case 'ALERT_DISPLAY': 
      return Object.assign({}, state, { alertShow: action.display }); 
    } 
    return state; 
} 

2.操作和異步操作:

行動來調整警報的顯示設定,並異步動作執行讀取和產生正確的結果。

export const ALERT_DISPLAY = 'ALERT_DISPLAY ' 
export function alertDisplay(display) 
{ 
    return { 
     type: ALERT_DISPLAY, 
     display 
    } 
} 

export function showAlert() 
{ 
    return function (dispatch) 
    { 
     fetch('api').then(function() 
     { 
      dispatch(alertDisplay(true)) 
     }); 

    } 

} 

3.在連接組件:

連接的組件。無需分享參考資料,參考資料將被使用,但組件會對其給定的道具做出反應並相應地設置警報。

import Alert from Alert.js; 

class Dummy extends React.Component 
{ 
    constructor(props) 
    { 
     super(props); 

     this.setAlert = this.setAlert.bind(this); 
    } 

    setAlert() 
    { 
     if(this.props.alertShow) 
      this._alert.show('Cool response!'); 
     else 
      this._alert.hide(); 

    } 

    componenDidMount() 
    { 
     setAlert(); 
    } 

    componentDidUpdate(prevProps, prevState) 
    { 
     if(prevProps.alertShow !== this.props.alertShow) 
      setAlert(); 
    } 

    render() 
    { 
     return 
     (
      <div> 
       <Alert ref={a => this._alert = a} /> 
       <Button onClick={this.props.showAlert}/> 
      </div> 
     ) 
    } 
} 
Dummy = connect(

    state => 
    ({ 
     alertShow: state.Dummy.alertShow 
    }), 

    dispatch => 
    ({ 
     showAlert:() => dispatch(showAlert(true)) 
    }) 

)(Dummy); 
+0

我認爲您忘記導入showAlert操作在連接的虛擬組件上。 –

2

首先,您是否嘗試在handleClick中使用箭頭函數?

handleClick() { 
    fetch('api').then(() => { 
     this.setState({ clicked: true }); 
     this._alert.show('Cool response!'); 
    }); 
} 

可能影響this

上下文。另一方面,如果你使用的終極版,你應該創建兩個動作。例如,fetchAPI()和。