【问题标题】:React-Redux: What is the canonical way to bind a keypress action to kick off a reducer sequence?React-Redux:绑定按键操作以启动 reducer 序列的规范方法是什么?
【发布时间】:2017-01-17 09:43:06
【问题描述】:

这是 react-redux 的一个新手问题,我花了几个小时四处寻找才找到,所以我发布了这个问题,然后为后代回答,也许还有代码审查。

我正在使用 react-redux 创建一个游戏,我想使用 WASD 键在小地图上移动角色。 (这只是一个更大努力的实践示例)。地图只是由一堆彩色的<div>s 组成。

据我了解,我需要以某种方式将 keypress 事件绑定到 React DOM 中的某些内容,以便触发 mapDispatchToProps,然后开始重新评估减速器。问题是,这是一个按键,没有什么可以绑定的。我正在使用 jquery 来绑定按键并调用函数。

相关查询:

【问题讨论】:

    标签: reactjs redux react-redux


    【解决方案1】:

    您基本上可以在keypress 事件处理程序中触发操作

    class App extends React.Component {
    
      constructor() {
        super();
        this.handleKeyPress = this.handleKeyPress.bind(this);
      }
    
      handleKeyPress(event) {
        // you may also add a filter here to skip keys, that do not have an effect for your app
        this.props.keyPressAction(event.keyCode);
      }
    
      componentDidMount() {
         document.addEventListener('keypress', this.handleKeyPress);
      }
    
      componentWillUnmount() {
         document.removeEventListener('keypress', this.handleKeyPress);
      }
    
      render() {
        return <div>Your game content</div>;
      }
    }
    
    export default connect(mapStateToProps, {keyPressAction})(App)
    

    handleKeyPress 调用动作创建者,这会将动作下推到减速器。

    【讨论】:

      【解决方案2】:

      对于那些在带有函数类的 typescript 中使用更新的 redux 的人,你可能想要这样的东西:

      import { useDispatch } from "react-redux";
      import { useEffect } from "react";
      
      const App = () => {
        const dispatch = useDispatch();
      
        useEffect(() => {
          document.addEventListener('keydown', handleKeyDown);
          document.addEventListener('keyup', handleKeyUp);
          return function cleanup() {
            document.removeEventListener('keydown', handleKeyDown);
            document.removeEventListener('keyup', handleKeyUp);
          };
        });
      
        const handleKeyDown = (event) => {
          console.debug("Key event", event);
          dispatch(handleKeyInput(game_state, connection_status, event.key));
          document.removeEventListener('keydown', handleKeyDown);
        };
      
        const handleKeyUp = (event) => {
          document.addEventListener('keydown', handleKeyDown, {once: true});
        };
      }
      

      https://reactjs.org/docs/hooks-effect.html

      【讨论】:

        【解决方案3】:

        解决方案改编自这里:

        addEventListener react redux with mapped dispatch

        关键是删除 jquery 并使用 document.addEventListener 将其绑定到 react 组件中。这是工作代码的摘录:

        ////////////////////////////////////////////
        ////////////////////// containers
        ////////////////////////////////////////////
        class GameMap extends React.Component{
          renderMap(){
            console.log('renderMap')
            console.log(this.props)
            return this.props.gamemap.map((tile) => {
              //const x = "tile " + tile
              return <div className={"tile " + tile}></div>
            })
          }
          render() {
            console.log('GameMap.render()')
            return (
              <div className="GameMap">
                {this.renderMap()}
              </div>)
          } 
          componentDidMount() {
            console.log("componentDidMount")
            console.log(this)
            // the following line won't be bound to the store here...
            document.addEventListener("keydown", this.props.keyPress );
          }
        }
        function GMmapStateToProps(state){
          //from here goes into this.props
          console.log('BLmapStateToProps')
          console.log(state)
          const gamemap = state.gamemap.gamemap.map((a) => {
            switch (a){
              case 1:
                return "tile-free"
              case 9:
                return "tile-user"
                     }
            return "tile-wall"
          })
          return{
            gamemap: gamemap
          }
        }
        function GMmapDispatchToProps(dispatch){
          //when selectbook called, pass result to all reducers
          console.log('GMmapDispatchToProps')
          return bindActionCreators({keyPress: keyPress}, dispatch)
        }
        const VGameMap = connect(GMmapStateToProps, GMmapDispatchToProps)(GameMap)
        
        ////////////////////////////////////////////
        ////////////////////// actions
        ////////////////////////////////////////////
        // actions/index.js action creator
        function keyPress(key) {
          console.log('keyPress: ', key)
          console.log(key.key)
          var vector = ""
          switch(key){
            case 'w', 'ArrowUp':
              vector = {x:0,y:1}
            case 's', 'ArrowDown':
              vector = {x:0,y:-1}
            case 'a', 'ArrowLeft':
              vector = {x:-1,y:0}
            case 'd', 'ArrowRight':
              vector = {x:1,y:0}
                    }
          return {
            type: "KEYPRESS",
            payload: vector
          } // this is an action created
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-08-04
          • 2021-07-23
          • 2018-08-12
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多