⚛️

React Patterns Wiki

Community Wiki & Forum

⚛️

Category

Frontend Development

Last Updated

January 2024

Contributors

42 active contributors

Related Topics

HTMLJavaScriptWeb Design

Tips, tricks, and best practices for React development

Custom Hooks Pattern

Extract reusable logic into custom hooks to keep components clean and promote code reuse across your application.

// useLocalStorage hook
function useLocalStorage(key, initialValue) {
  const [storedValue, setStoredValue] = useState(() => {
    try {
      const item = window.localStorage.getItem(key);
      return item ? JSON.parse(item) : initialValue;
    } catch (error) {
      return initialValue;
    }
  });

  const setValue = (value) => {
    try {
      setStoredValue(value);
      window.localStorage.setItem(key, JSON.stringify(value));
    } catch (error) {
      console.error(error);
    }
  };

  return [storedValue, setValue];
}

// Usage
function Component() {
  const [name, setName] = useLocalStorage('name', 'Anonymous');
  return <input value={name} onChange={(e) => setName(e.target.value)} />;
}

Compound Components

Create flexible component APIs by splitting functionality across multiple components that work together.

// Compound component pattern
function Select({ children, value, onChange }) {
  return (
    <SelectContext.Provider value={{ value, onChange }}>
      <div className="select">{children}</div>
    </SelectContext.Provider>
  );
}

function Option({ value, children }) {
  const { value: selectedValue, onChange } = useContext(SelectContext);
  return (
    <button
      className={selectedValue === value ? 'active' : ''}
      onClick={() => onChange(value)}
    >
      {children}
    </button>
  );
}

// Usage
<Select value={selected} onChange={setSelected}>
  <Option value="a">Option A</Option>
  <Option value="b">Option B</Option>
</Select>

Render Props

Pass a function as a prop to share code between components while giving consumers full control over rendering.

// DataFetcher with render prop
function DataFetcher({ url, render }) {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    fetch(url)
      .then(res => res.json())
      .then(data => {
        setData(data);
        setLoading(false);
      });
  }, [url]);

  return render({ data, loading });
}

// Usage
<DataFetcher
  url="/api/users"
  render={({ data, loading }) => (
    loading ? <Spinner /> : <UserList users={data} />
  )}
/>

Discussion (0)

Your avatar

No comments yet. Be the first to join the discussion!