javascript - ReactJS - Handle parent event in child event handler - Stack Overflow

I have a react container where I want to capture mousemove events. That is pretty straight forward. Fur

I have a react container where I want to capture mousemove events. That is pretty straight forward. Further I have a react sub-ponent rendered by the container where actually the logic for the mousemove event handler resides. So I need to pass/delegate the mousemove event from the container parent to the child and get the mousemove handler of the child invoked. How is that done properly?

I need to capture the mouse event in the container rather than the sub-ponent because the container is a larger HTML element in the DOM and I need to capture events in that whole area.

The mousemove-handler-logic needs to be in the sub-ponent as it encapsulates some functionality the container should not be aware of.

The render method of the container:

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

I tried an approach where MyContainer sets callback functions for MySubComponent to retrieve its DOM Node and register handler with addEventListener but that did not work consistently as occasionally the DOM Node got undefined:

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-ponent="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);
    }

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

    ponentWillUnmount() {
        // 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
} 

I also tried to call the mousemove event handler in MySubComponent directly from MyContainer via this.refs.SubComponent.handleMousemove but that is regarded to be bad practise in react-redux.

I have a react container where I want to capture mousemove events. That is pretty straight forward. Further I have a react sub-ponent rendered by the container where actually the logic for the mousemove event handler resides. So I need to pass/delegate the mousemove event from the container parent to the child and get the mousemove handler of the child invoked. How is that done properly?

I need to capture the mouse event in the container rather than the sub-ponent because the container is a larger HTML element in the DOM and I need to capture events in that whole area.

The mousemove-handler-logic needs to be in the sub-ponent as it encapsulates some functionality the container should not be aware of.

The render method of the container:

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

I tried an approach where MyContainer sets callback functions for MySubComponent to retrieve its DOM Node and register handler with addEventListener but that did not work consistently as occasionally the DOM Node got undefined:

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-ponent="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);
    }

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

    ponentWillUnmount() {
        // 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
} 

I also tried to call the mousemove event handler in MySubComponent directly from MyContainer via this.refs.SubComponent.handleMousemove but that is regarded to be bad practise in react-redux.

Share Improve this question edited Oct 20, 2021 at 22:40 Brian Tompsett - 汤莱恩 5,89372 gold badges61 silver badges133 bronze badges asked Jul 4, 2016 at 6:23 MichbeckableMichbeckable 1,8911 gold badge30 silver badges44 bronze badges 4
  • your question has nothing to do redux. Can you have the onMouseMove event directly handled by MySubComponent? it makes more sense if the logic is pletely handled by MySubComponent – xiaofan2406 Commented Jul 4, 2016 at 6:43
  • Could you give the code of your first approach, so we can understand what went wrong? – Damien Leroux Commented Jul 4, 2016 at 7:07
  • @xiaofan2406: See my edit on the question. I need to capture the event on the large HTML container element rather than on the quite small sub-ponent. – Michbeckable Commented Jul 4, 2016 at 7:32
  • @DamienLeroux: I added the code. You can see that I provide a callback function getContainerRef to MySubComponent where it can retrieve the DOM ref of the container and register the event handlers itself. But when container got unmounted the provided ref always turned undefined and the event handler could not be removed. – Michbeckable Commented Jul 4, 2016 at 7:47
Add a ment  | 

2 Answers 2

Reset to default 5

Working with refs should be avoided if possible.

If you want to capture the onMouseMove in the parent container I think best is to just pass the relevant properties of the event to your child ponent. When the values change in the parent ponentWillReceiveProps and shouldComponentUpdate in the child ponent get invoked and you can react to it.

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>;
    }
}

And your Child ponent:

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>;
  }
}

However your implementation in the child ponent will look like. It just has to know about its props and nothing about its parent ponent.

react ponent lifecycle: https://facebook.github.io/react/docs/ponent-specs.html

Although your mousemove should be in the subponent and your container should use mapDispatchtoProps, like this

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

and in your subponent dispatch(onmousemoveAction)

But if you still want to have logic in subponent do

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

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744826344a4595820.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信