ReactJS - 在子事件处理程序中处理父事件

ReactJS - Handle parent event in child event handler

我有一个 React 容器,我想在其中捕获 mousemove 事件。这很简单。此外,我还有一个由容器呈现的反应子组件,其中实际上包含 mousemove 事件处理程序的逻辑。所以我需要 pass/delegate 从父容器到子容器的 mousemove 事件,并调用子容器的 mousemove 处理程序。如何正确完成?

我需要在容器而不是子组件中捕获鼠标事件,因为容器是 DOM 中较大的 HTML 元素,我需要在整个区域中捕获事件.

mousemove-handler-logic 需要在子组件中,因为它封装了一些容器不应该知道的功能。

容器的渲染方法:

render() {
    return (
        <div data-component="MyContainer"
             onMouseMove={(event) => this.handleMousemove(event)}>
            
            <MySubComponent {// ... give some props here}>
        </div>
    );
}

我尝试了一种方法,其中 MyContainerMySubComponent 设置回调函数以检索其 DOM 节点并向 addEventListener 注册处理程序,但这种方法偶尔无法始终如一地工作DOM 节点未定义:

export default class MyContainer extends Component {
    constructor(props) {
        super(props);
        this.state = {};

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

    getContainerRef() {
        return this.refs['containerWrap'];
    }
    
    render() {
        return (
            <div data-component="MyContainer"
                 ref="containerWrap"
                 onMouseMove={(event) => this.handleMousemove(event)}>
                
                <MySubComponent getContainerRef={this.getContainerRef} />
            </div>
        );
    }
}

export default class MySubComponent extends Component {
    constructor(props) {
        // ... init something
        
        this.handleMousemove = this.handleMousemove.bind(this);
    }

    componentDidMount() {
        // add event listener for parent application frame
        let containerDOM = this.props.getContainerRef();
        containerDOM.addEventListener('mousemove', this.handleMousemove, false);
    }

    componentWillUnmount() {
        // remove event listener from parent application frame
        let containerDOM= this.props.getContainerRef();
        containerDOM.removeEventListener('mousemove', this.handleMousemove, false);
    }
    
    handleMousemove(event) {
        // handle the event
    }
    
    // ... more methods
} 

我还尝试通过 this.refs.SubComponent.handleMousemove 直接从 MyContainer 调用 MySubComponent 中的 mousemove 事件处理程序,但这在 react-redux 中被认为是不好的做法。

虽然你的 mousemove 应该在子组件中并且你的容器应该使用 mapDispatchtoProps,像这样

const mapDispatchToProps = (dispatch) => {
  return {
    onmousemoveAction: (id) => {
      dispatch(toggleTodo(id))
    }
  }
}

并且在你的子组件 dispatch(onmousemoveAction)

但是如果您仍然希望在子组件中有逻辑,请执行

this.refs.mysubcomponent.dispatchEvent(new Event('mousedown'))

尽可能避免使用 refs

如果你想在父容器中捕获 onMouseMove 我认为最好的方法是将 event 的相关属性传递给你的子组件。当父组件 componentWillReceiveProps 和子组件中的 shouldComponentUpdate 的值发生变化时,您可以对其做出反应。

class Container extends React.Component{
  constructor(props) {
    super(props);
      this.state = {
        mouseX: 0,
        mouseY: 0
      };
    }
  handleMouse(event) {
    event.preventDefault();
    this.setState({
      mouseX: event.clientX,
      mouseY: event.clientY
    });
  }

  render() {
    return <div onMouseMove={(event) => this.handleMouse(event)} className="demo">
        <Child x={this.state.mouseX} y={this.state.mouseY} />
    </div>;
    }
}

你的子组件:

class Child extends React.Component {
  shouldComponentUpdate(nextProps, nextState) {
    return this.handleMouseMove(nextProps.x, nextProps.y);
  }
  handleMouseMove(x, y) {
    if (x < 150) { // return true to invoke render for some conditions
      // your code
      return true;
    }  
    return false;
  }

  render() {
    return <div>Child Component</div>;
  }
}

但是您在子组件中的实现看起来像。它只需要了解其 props 而无需了解其父组件。

反应组件生命周期:https://facebook.github.io/react/docs/component-specs.html