React: How to Detect a Click Outside/Inside a Component

Last updated on June 13, 2022 A Goodman Loading... Post a comment

This concise and straight-to-the-point article shows you the fastest and easiest way to detect if the user clicks somewhere outside a specific component in a React application. We’ll discuss the technique to get the job done and then examine a complete example of applying that knowledge in practice. The example will be written in both Javascript and TypeScript (you can ignore the part you don’t care about). No third-party libraries are required.

Without any further ado (like explaining what React is or talking about its history), let’s get started.

What Is The Point?

Our strategy to check if a click is performed inside or outside a given component is to use the useRef() hook and the global event window.onclick. It sounds confusing. Let’s continue.

1. Add a ref to the component, like this:

const boxRef = useRef();

// Connect our ref to the component
<div ref={boxRef}>{/* ... */}</div>

2. The window.onclick event will be fired when the user clicks anywhere on the page. To determine whether the click position is inside or outside our component, combine window.onclick with the useEffect() hook as follows:

useEffect(() => {
    window.onclick = (event) => {
      if (event.target.contains(boxRef.current)
        && event.target !== boxRef.current) {     
        console.log(`You clicked Outside the box!`);
      } else {     
        console.log(`You clicked Inside the box!`);
      }
    }
}, []);

For more clarity, please see the complete example below.

Example

App Preview

The tiny demo we’re going to build displays a red box on the screen. When the user clicks inside the box, some red text will show up. If the user clicks outside the box, some blue text will appear.

Here’s how it works:

Javascript Code

If you prefer TypeScript to Javascript, just skip this section and jump to the next one. Otherwise, see the steps below.

1. Create a brand new React app:

npx create-react-app kindacode-example

The name is totally up to you.

2. The full source code for src/App.js (with explanations):

// KindaCode.com
// src/App.js
import { useRef, useEffect, useState } from 'react'


function App() {
  // This ref will be connected to the box
  const boxRef = useRef();

  // These variables indicate the click is outside or inside the box
  const [isInside, setIsInside] = useState();
  const [result, setResult] = useState();

  useEffect(() => {
    window.onclick = (event) => {
      if (event.target.contains(boxRef.current)
        && event.target !== boxRef.current) {
        setIsInside(false);
        setResult(`You clicked Outside the box at ${new Date().toLocaleString()}`);
      } else {
        setIsInside(true);
        setResult(`You clicked Inside the box at ${new Date().toLocaleString()}`);
      }
    }
  }, []);

  return (
    <div style={styles.container}>
      {/* The box */}
      <div
        ref={boxRef}
        style={styles.box}>
        <h1 style={styles.boxText}>KindaCode.com</h1>
      </div>

      {/* Display some text about the click location */}
      <div style={styles.result}>
        <h2 style={isInside ? styles.inside : styles.outSide}>{result}</h2>
      </div>
    </div>
  );
}

// Styling 
const styles = {
  container: {
    padding: 50
  },
  box: {
    width: 400,
    height: 300,
    cursor: 'pointer',
    background: 'orangered',
    display: 'flex',
    justifyContent: 'center',
    alignItems: 'center'
  },
  boxText: {
    color: 'white'
  },
  result: {
    marginTop: 30
  },
  inside: {
    color: 'red'
  },
  outSide: {
    color: 'blue'
  }
}

export default App;

3. Get the app up and running:

npm start

And go to http://localhost:3000 to try your work.

TypeScript Code

1. Start a new React project with TypeScript:

npx create-react-app kindacode-example-ts --template typescript

2. Replace all the default source code in your src/App.tsx file with the following:

// KindaCode.com
// src/App.js
import React, { useRef, useEffect, useState } from 'react'


function App() {
  // This ref will be connected to the box
  const boxRef = useRef<HTMLDivElement>(null);

  // These variables indicate the click is outside or inside the box
  const [isInside, setIsInside] = useState<boolean>();
  const [result, setResult] = useState<string>('');

  useEffect(() => {
    window.onclick = (event: MouseEvent) => {
      // type casting for window.onclick event
      // you can extend this union type if your app requires more than just <div>, <input>, <p>, <button>, and headings
      const target = event.target as HTMLDivElement
        | HTMLInputElement
        | HTMLParagraphElement
        | HTMLButtonElement
        | HTMLHeadingElement;

      if (target?.contains(boxRef.current) && target !== boxRef.current) {
        setIsInside(false);
        setResult(`You clicked Outside the box at ${new Date().toLocaleString()}`);
      } else {
        setIsInside(true);
        setResult(`You clicked Inside the box at ${new Date().toLocaleString()}`);
      }
    }
  }, []);

  return (
    <div style={styles.container}>
      {/* The box */}
      <div
        ref={boxRef}
        style={styles.box}>
        <h1 style={styles.boxText}>KindaCode.com</h1>
      </div>

      {/* Display some text about the click location */}
      <div style={styles.result}>
        <h2 style={isInside ? styles.inside : styles.outSide}>{result}</h2>
      </div>
    </div>
  );
}

// Styling 
const styles: { [key: string]: React.CSSProperties } = {
  container: {
    padding: 50
  },
  box: {
    width: 400,
    height: 300,
    cursor: 'pointer',
    background: 'orangered',
    display: 'flex',
    justifyContent: 'center',
    alignItems: 'center'
  },
  boxText: {
    color: 'white'
  },
  result: {
    marginTop: 30
  },
  inside: {
    color: 'red'
  },
  outSide: {
    color: 'blue'
  }
}

export default App;

3. Boot it up:

npm start

Conclusion

You’ve learned how to know whether a click happens outside a certain component in React with hooks and functional components. This is helpful in many real-world scenarios, such as when you show a dialog and want to close it by clicking outside its area.

If you’d like to explore more new and interesting stuff about modern React, take a look at the following articles:

You can also check our React topic page and Next.js topic page for the latest tutorials and examples.

Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments

Related Articles