iwantcoding.com
🔥 Daily 👥 Rooms 🏆 Top Log in Sign up

React Examples

A handful of React patterns you reach for over and over - data fetching, forms with Zod, optimistic UI, infinite scroll, debounced search.

React by example

EXAMPLE
// 1. Data fetching with TanStack Query
import { useQuery } from '@tanstack/react-query';

function User({ id }: { id: string }) {
  const { data, isPending, error } = useQuery({
    queryKey: ['user', id],
    queryFn: () => fetch(\`/api/users/${id}\`).then((r) => r.json()),
    staleTime: 60_000,
  });
  if (isPending) return <p>loading</p>;
  if (error) return <p>error: {String(error)}</p>;
  return <p>{data.name}</p>;
}


// 2. Form with Zod + react-hook-form
import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { z } from 'zod';

const Schema = z.object({
  email: z.string().email(),
  password: z.string().min(8),
});
type Input = z.infer<typeof Schema>;

function Login() {
  const { register, handleSubmit, formState: { errors, isSubmitting } } =
    useForm<Input>({ resolver: zodResolver(Schema) });

  const onSubmit = async (data: Input) => { /* call api */ };

  return (
    <form onSubmit={handleSubmit(onSubmit)} className='space-y-2'>
      <input {...register('email')} type='email' />
      {errors.email && <p>{errors.email.message}</p>}
      <input {...register('password')} type='password' />
      {errors.password && <p>{errors.password.message}</p>}
      <button disabled={isSubmitting}>Sign in</button>
    </form>
  );
}


// 3. Optimistic UI with useOptimistic (React 19)
import { useOptimistic, useTransition } from 'react';

function TodoList({ initial, onAdd }: { initial: Todo[]; onAdd: (text: string) => Promise<void> }) {
  const [pending, start] = useTransition();
  const [items, addOptimistic] = useOptimistic(initial, (state, text: string) => [
    ...state,
    { id: 'tmp', text, pending: true },
  ]);
  return (
    <>
      <form action={(fd) => {
        const text = String(fd.get('text'));
        start(async () => {
          addOptimistic(text);
          await onAdd(text);
        });
      }}>
        <input name='text' />
      </form>
      <ul>{items.map((t) => <li key={t.id} style={{ opacity: t.pending ? 0.5 : 1 }}>{t.text}</li>)}</ul>
    </>
  );
}


// 4. Infinite scroll with TanStack Query
import { useInfiniteQuery } from '@tanstack/react-query';

const { data, fetchNextPage, hasNextPage } = useInfiniteQuery({
  queryKey: ['posts'],
  queryFn: ({ pageParam = null }) =>
    fetch(\`/api/posts?cursor=${pageParam || ''}\`).then((r) => r.json()),
  getNextPageParam: (last) => last.nextCursor ?? undefined,
  initialPageParam: null,
});


// 5. Debounced search
import { useState, useEffect } from 'react';

function useDebounce<T>(value: T, ms = 300) {
  const [v, setV] = useState(value);
  useEffect(() => {
    const id = setTimeout(() => setV(value), ms);
    return () => clearTimeout(id);
  }, [value, ms]);
  return v;
}

const [q, setQ] = useState('');
const dq = useDebounce(q, 250);
useEffect(() => {
  if (dq.length < 2) return;
  fetch(\`/api/search?q=${encodeURIComponent(dq)}\`).then(/* ... */);
}, [dq]);

Why it matters

These five patterns cover most of what an app actually does - fetch data, accept input, react optimistically, paginate, search. Pick a query lib, a form lib, and a UI primitive lib and stop reinventing.

Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.

Example

Example
// Common snippets — see lesson body.
const App = () => <h1>iwantcoding.com React Examples</h1>;
Try it Yourself »

Discussion

Loading…