user1261710
user1261710

Reputation: 2639

How to ensure an event listener is always called inside a ReactJS child component?

I have a ReactJS component below. I want to listen for a key down even if my component is not in focus. It will always be rendered but it is not the only component on the web page. The event listener will call a function when I push the SHIFT key down. The component is not the topmost component on my web page; it has a parent.

Component extends React.Component {

    componentWillMount(): void {
        document.addListener('keyDown', this._handleKeyDown);
    }

    componentWillUnmount(): void {
        document.removeListender('keyDown', this._handleKeyDown);
    }

}

Sometimes it will behave properly when I push a button but sometimes I actually have to click on this component again to get it to acknowledge the key press.

How can I ensure it always listens for the key press? Is it advisable to add an event listener to document in a lower level component?

Upvotes: 0

Views: 79

Answers (2)

user1261710
user1261710

Reputation: 2639

It wasn't working because I had a very large invisible div in front of my clickable element. I made the div have no pointer events and then I was able to get my keyDown function consistently working.

The technique above will work. You can put document.addEventListener inside a child React component.

Upvotes: 0

devellopah
devellopah

Reputation: 471

pen here -> http://codepen.io/dagman/pen/mAOrVP

const App = ({ 
    handleOnKeyDown,
    keyCode
}) => (
    <div>
        <input 
            style={styles.input}
            onKeyDown={handleOnKeyDown} 
            placeholder="Press any key to see it's code on right" 
        />
        <span style={styles.span}>{keyCode}</span>
    </div>
);

class AppContainer extends React.Component {
    constructor(props) {
        super();
        this.state = {
            keyCode: null
        };
    }
    handleOnKeyDown(e) {
        this.setState({
            keyCode: e.keyCode
        });
    }
    render() {
        return(
            <App 
                handleOnKeyDown={this.handleOnKeyDown.bind(this)}
                keyCode={this.state.keyCode}
            />
        );
    }
}

const mountNode = document.getElementById('app');
const styles = {
    input: {
        width: 300,
        height: 50
    },
    span: {
        color: 'white',
        marginLeft: 5
    }
};

ReactDOM.render(
    <AppContainer />,
    mountNode
);

Is it what you were asking about?

Upvotes: 1

Related Questions