Regex Fundamental
Used in this guide:Introduction
Regex (short for Regular Expressions) is a powerful tool used to match and extract patterns from strings—commonly applied in tasks like validating input, filtering data, and parsing content. In this tutorial, we’ll walk through three beginner-friendly examples inside a real React/Next.js app to help you understand how regex works and how you can use it effectively in your own projects.
Why Regex?
- Pattern matching in strings
- Substring extraction
- Validation
- Replacement
- Filtering
Example 1: Validation
What if you want to make sure users only enter English letters as their username? Let’s say you’re building a signup form and want to enforce a simple rule to only allow alphabet characters (a–z) with no numbers, no spaces, no symbols.
This is a perfect use case for Regular Expressions (Regex). In this example, we use the regex pattern /^[a-z]+$/i to validate the input:
- The pattern is wrapped inside forward slashes (/.../), this is JavaScript’s way of defining a regular expression.
- Think of ^ and $ as boundary markers that wrap your validation logic. Without them, the pattern can match anywhere in the string — but with them, the entire string must follow the rules exactly.
- [a-z] means allow one English letters. [a-z]+ means allow one or more English characters.
- The i flag makes the match case-insensitive, so both uppercase and lowercase letters are accepted.
So the whole pattern matches strings made entirely of English letters (like John, Jane, or Awesome), and rejects anything else (like john_doe, 123Jane, or awesome!).
'use client'
import { useState } from "react"
export default function UsernameValidatorPage() {
const [username, setUsername] = useState('');
const isValid = /^[a-z]+$/i.test(username);
return (
<main className="flex flex-col gap-[16px] items-center justify-center h-[60vh] px-4 bg-gray-600 text-gray-200">
<h1 className="font-semibold text-2xl">Username Validator</h1>
<input
type="text"
placeholder="Enter username (a-z only)"
value={username}
onChange={(e) => setUsername(e.target.value)}
className="w-[300px] py-2 px-4 bg-slate-400 text-slate-800 text-center"
/>
{username && (
<p className={isValid ? 'text-teal-300' : 'text-rose-300'}>
{username && isValid ? 'Valid Username' : 'Invalid Username'}
</p>
)}
</main>
)
}Note:
In JavaScript, regex is commonly used with the .test() method to check whether a string matches a specific pattern. The .test() method returns a boolean, true if the pattern is found, and false if it’s not.
Example 2: Category Filtering
In this example, we introduce RegExp(). It works like /.../ but allows you to build regular expressions dynamically using variables — perfect for cases like category filters or user input.
This example demonstrates how to filter items based on a selected category using RegExp() which is handy when you need dynamic matching logic. It also introduces two helpful JavaScript methods: .flatMap() and .filter().
'use client'
import { useState } from "react";
const AllBooks = [
{
category: "fiction",
books: ["fiction-01", "fiction-02", "fiction-03"],
},
{
category: "crime",
books: ["crime-01", "crime-02", "crime-03"],
},
];
export default function FilterBooksPage() {
const [selectedCategory, setSelectedCategory] = useState<string>("all");
const getFilteredBooks = () => {
const allBooks = AllBooks.flatMap(item => item.books);
if (selectedCategory == "all") return allBooks;
const pattern = new RegExp(`^${selectedCategory}-`, 'i'); // matches e.g. "fiction-"
return allBooks.filter(title => pattern.test(title));
}
const filteredBooks = getFilteredBooks();
return (
<main className="flex flex-col gap-[16px] items-center justify-center h-[60vh] px-4 bg-gray-600 text-gray-200">
<h1 className="font-semibold text-lg">Filter Books</h1>
<div className="flex justify-center gap-4 mb-8">
<button
onClick={() => setSelectedCategory("fiction")}
className="py-2 px-4 bg-teal-300 text-slate-700 hover:bg-teal-500"
>Fiction</button>
<button
onClick={() => setSelectedCategory("crime")}
className="py-2 px-4 bg-teal-300 text-slate-700 hover:bg-teal-500"
>Crime</button>
<button
onClick={() => setSelectedCategory("all")}
className="py-2 px-4 bg-teal-300 text-slate-700 hover:bg-teal-500"
>All</button>
</div>
<div className="flex gap-4 flex-wrap w-[400px] justify-center">
{filteredBooks.map((book, index) => (
<span key={index} className="py-2 px-4 border-slate-400 border-1">{book}</span>
))}
</div>
</main>
)
}What This Does
Imagine you have a list of book categories, each with its own array of book titles. You want users to click on a category (e.g. Fiction or Crime), and instantly see only the books in that category.
To accomplish this:
- We flatten all books from all categories using .flatMap().
- We dynamically build a regex pattern with new RegExp() to match books that belong to the selected category.
- We filter the list of all books using .filter() and the regex pattern.
const allBooks = AllBooks.flatMap(item => item.books); It goes through each item, accesses the books array (hence item.books), and flattens all of them into a single array. So when we map through allBooks, we can display all books.
We use RegExp() instead of /.../ so we can insert the selectedCategory variable into the pattern dynamically.
allBooks.filter(book => pattern.test(book)); loops through each item inside allBooks variable and returns only the ones that match the pattern effectively filtering the array based on the selected category.
Example 3: Extract Hashtags from Input
In this example, we use regex to extract hashtags in real time as the user types. The extracted hashtags are displayed as pill-style tags below the input field.
'use client'
import { useState } from "react"
export default function FilterInputPage() {
const [userInput, setUserInput] = useState("");
const hashtags = userInput.match(/#\w+/g);
return (
<div className="flex flex-col w-full max-w-[600px] h-[60vh] items-center justify-center gap-4 mx-auto bg-slate-700">
<h1 className="font-semibold text-lg">Filter Input</h1>
<p className="opacity-70">When you type a hashtag (like #example), it will appear as a pill below.</p>
<input
type="text"
onChange={(e) => setUserInput(e.target.value)}
className="w-[400px] py-2 px-4 bg-slate-400 text-slate-800"
placeholder="Type hastags here..."
/>
{ hashtags && (
<div className="flex gap-2 justify-center w-full p-4">
{hashtags.map((item, index) => (
<span key={index} className="py-1 px-2 bg-teal-400 text-slate-700 text-[14px] rounded-lg">{item}</span>
))}
</div>
)}
</div>
)
}We use the .match() method with the pattern /#\w+/g which breaks down as:
- # = the literal hash symbol
- \w+ = matches one or more word characters (a-z, A-Z, 0-9, and _)
- The g flag means global, so it finds all matches in the string