2016-12-13 53 views
2

我正在使用React和Electron構建桌面應用程序。 由於它快速增長,我意識到需要像Redux這樣的狀態管理來避免在組件之間傳遞許多屬性。 我開始閱讀Redux官方documentation,但仍然無法弄清楚如何在我的情況下實現它。我卡住了!如何使用React-Redux模擬事件?

例如,我有一個主要的App組件,呈現許多子組件。其中一個有一個按鈕。點擊後,它應該向商店派發一個「事件」,因此主要的App可以起作用。我怎麼能做到這一點? 我無法找到事件的概念,並且我甚至在如何開始使用Redux時遇到了困難。

爲什麼要舉辦活動?因爲在這種情況下派發一個操作並修改應用程序狀態似乎很愚蠢。我只想通知根組件根據用戶操作發送操作。 用戶與應該告訴容器組件進行API調用或開始捕獲音頻/相機的表示組件進行交互。

對於我所知道的,到目前爲止,實現這一目標的唯一方法是對狀態進行變異,以便另一個偵聽變化的組件檢測到一個特殊的值,意思是「嘿,讓我們這樣做」,然後再次改變狀態以說「嗨,我正在做這件事「,當它完成後,狀態再次改變,」嘿,它完成了「。

有人可以指點我正確的方向嗎?

回答

4

用戶與應該告訴容器組件進行API調用或開始捕獲音頻/相機的表示組件進行交互。

也許你的容器組件做得比應該多。考慮其中反應的組分做不超過兩件事情:如果你沒有使用終極版,並希望基於道具

  • 處理用戶輸入(調度事件)
    1. 顯示DOM元素點擊按鈕時調用API,這可能看起來像:

      class App extends Component { 
          state = { data: {} } 
      
          makeAPICall() { 
          fetch(url).then(data => this.setState({ data })) 
          } 
      
          render() { 
          <Child 
           data={this.state.data} 
           makeAPICall={this.makeAPICall} 
          /> 
          } 
      } 
      
      let Child = ({ data, makeAPICall }) => (
          <button onClick={makeAPICall}>Call API!</button> 
      ) 
      

      App組件負責存儲全局狀態和處理事件,但我們必須通過組件樹傳遞狀態和App的處理程序,很可能通過組件永遠不會使用這些道具。

      通過添加Redux,您的應用程序現在擁有更好的處理API調用或打開相機等副作用的地方。中間件!

      讓這(糟糕的)插圖幫助你:

      enter image description here

      因此,現在你App組件可以像所有其他的正常表象組件,只需根據商店的道具和處理顯示數據任何用戶輸入/調度動作,如果需要的話。讓我們使用thunk中間件

      // actions.js 
      export let makeAPICall =() => { 
          return dispatch => { 
          fetch(url).then(data => dispatch({ 
           type: 'API_SUCCESS', 
           payload: data, 
          })).catch(error => dispatch({ type: 'API_FAIL', payload: error })) 
          } 
      } 
      
      // Child.js 
      import { connect } from 'react-redux' 
      import { makeAPICall } from './actions' 
      
      let Child = ({ dispatch }) => (
          <button onClick={() => dispatch(makeAPICall())}>Call API!</button> 
      ) 
      
      export default connect()(Child) 
      

      大約陣營應用這種方式是非常強大的思維更新上面的例子。關注的分離是非常完善的。組件顯示內容並處理事件。中間件負責處理任何副作用(如果需要的話),而且商店只是一個會導致React在其數據發生變化時重新呈現的對象。

      UPDATE:「模態問題」

      陣營應用可能有像情態動詞和工具提示一些全局的東西。不要去想「開放模式」事件。想一想「現在的模態內容是什麼?」。

      一個模式的設置可能看起來沿着這些線路:

      // modalReducer.js 
      function reducer (state = null, action) { 
          if (action.type === 'UPDATE_MODAL') { 
          return action.payload 
          } 
      
          // return default state 
          return state 
      } 
      
      // App.js 
      let App = connect(state => ({ modal: state.modal }))(
          props => 
          <div> 
           <OtherStuff /> 
           <Modal component={props.modal} /> 
          </div> 
      ) 
      
      // Modal.js 
      let Modal = props => 
          <div 
          style={{ 
           position: 'fixed', 
           width: '100vw', height: '100vh', 
           opacity: props.component ? 1 : 0, 
          }} 
          > 
          {props.component} 
          </div> 
      
      // Child.js 
      
      let Child = connect()(props => 
          <button onClick={e => 
          dispatch({ 
           type: 'UPDATE_MODAL' 
           payload: <YourAwesomeModal /> 
          }) 
          }> 
          Open your awesome modal! 
          </button> 
      ) 
      

      這僅僅是一個例子,但將工作的偉大!當state.modalnull你的Modal具有0不透明度並且不會顯示。當您調度UPDATE_MODAL並傳入組件時,模式將顯示您分派的任何內容,並將不透明度更改爲1,以便您可以看到它。稍後,您可以派遣{ type: 'UPDATE_MODAL', payload: null }關閉模式。

      希望這會給你一些想法!

      當然read this answer by Dan。他的方法是類似的,但存儲模式「元數據」與組件本身相比,它更適合像時間旅行等Redux fanciness

    +0

    這確實有幫助,但並沒有解決我的問題。我有一個模式對話框,它是根應用程序組件的一部分,子次級子組件有一個按鈕,單擊該對話框時需要顯示該對話框。我如何在沒有事件概念的情況下實現這一點,並且不需要將事件處理程序一直傳遞下去? – demian85

    +0

    啊我最喜歡的一個問題!添加這個。 – azium

    +0

    中間件是您需要傾聽操作並以某種方式做出響應的工具。也就是說,Dan Abramov寫了一篇關於[使用Redux管理模態對話框]的答案(http://stackoverflow.com/a/35641680/62937),並且我寫了一篇博客文章,建立在他的技術基礎上,以處理[從通用對話框](http://blog.isquaredsoftware.com/2016/11/posts-on-packtpub-generic-redux-modals-and-building-better-bundles/)。 – markerikson

    0

    是你認爲它看起來很愚蠢的原因,因爲你不希望你的表象組件被縮小-知道的?如果是這樣mapDispatchToPropsbindActionCreators可能幫助整理東西,例如:

    // App.js 
    import React from 'react'; 
    import { bindActionCreators } from 'redux'; 
    import { connect } from 'react-redux'; 
    import { someAction } from './actions'; 
    import Button from './Button'; 
    
    const App = ({ onButtonClick }) => (
        <div> 
         Hello. 
         <Button onClick={onButtonClick}>Click me.</Button> 
        </div> 
    ); 
    
    export default connect(null, dispatch => { 
        return bindActionCreators({ 
         onButtonClick: someAction 
        }, dispatch); 
    })(App); 
    
    // Button.js 
    import React from 'react'; 
    
    export default Button = ({ onClick, children }) => <button onClick={onClick}>{children}</button>; 
    

    正如你所看到的只是連接的容器組件是知道的動作,按鍵(甚至是應用程序)都沒有意識到點擊觸發行動。

    +0

    您是否忘記在connect()調用中導出應用程序? 請看我上面的評論。我想避免在主狀態樹中有一個屬性,它顯示「讓我們顯示一個對話框」,當對話框打開後不久需要刪除......這很愚蠢。我可以觀察操作並檢測組件何時想要以某種方式打開對話框? – demian85