如何使用React-Redux模拟事件?

dem*_*n85 4 javascript events store reactjs redux

我正在使用React和Electron构建桌面应用程序.由于它正在快速增长,我意识到我需要像Redux这样的某种状态管理来避免在组件之间传递许多属性.我开始阅读Redux官方文档,但仍然无法弄清楚如何在我的情况下实现它.我被卡住了!

例如,我有一个主要App组件,可以呈现许多子组件.其中一个有一个按钮.点击后,它应该向商店发送"事件",以便主要人员App可以采取行动.我怎么能做到这一点?我无法找到事件的概念,而且我已经开始讨论如何开始使用Redux.

为何举办活动 因为在这种情况下发送动作并修改应用程序状态对我来说似乎很愚蠢.我只想通知根组件根据用户操作调度操作.用户与表示组件交互,该表示组件应该告诉容器组件进行API调用或开始捕获音频/摄像机.

根据我现在所知,实现这一目标的唯一方法是改变状态,以便另一个侦听变化的组件检测到一个特殊值,意思是"嘿,让我们这样做",然后再次改变状态说"嘿,我是这样做",当它完成状态再次改变"嘿,它完成了".

有人能指出我正确的方向吗?

azi*_*ium 6

用户与表示组件交互,该表示组件应该告诉容器组件进行API调用或开始捕获音频/摄像机.

也许你的容器组件正在做的比它应该做的更多.考虑React组件不超过两件事的情况:

  1. 显示基于道具的DOM元素
  2. 处理用户输入(调度事件)

如果您没有使用redux并且想要在单击按钮时进行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>
)
Run Code Online (Sandbox Code Playgroud)

App组件负责存储全局状态和处理事件,但我们必须通过组件树传递该状态和App的处理程序,很可能通过永远不会自己使用这些道具的组件.

通过添加Redux,您的应用程序现在可以更好地处理API调用或打开相机等副作用.中间件!

让这个(糟糕的)插图帮助你:

在此输入图像描述

因此,现在您的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)
Run Code Online (Sandbox Code Playgroud)

以这种方式思考React应用程序是非常强大的.关注点的分离非常明确.组件显示内容和处理事件.中间件处理任何副作用(如果需要),并且存储只是一个对象,如果数据发生变化,将导致React重新呈现.

更新:"模态问题"

React应用程序可能包含一些全局内容,如模态和工具提示.不要考虑"开放模式"事件.想一想"目前的模态内容是什么?".

模态设置可能看起来沿着这些方向:

// 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>
)
Run Code Online (Sandbox Code Playgroud)

这只是一个例子,但效果会很好!当state.modalnull你的情态有0的不透明性和不显示.当您调度UPDATE_MODAL并传入一个组件时,模态将显示您发送的任何内容,并将不透明度更改为1,以便您可以看到它.之后你可以派遣{ type: 'UPDATE_MODAL', payload: null }关闭模态.

希望这能给你一些思考的东西!

Dan一定会读到这个答案.他的方法类似但存储模态"元数据"与组件本身相比,这更适合Redux的时尚旅行等.