2016-12-13 56 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