react-use-custom-hooks

website·Indexed 29 days ago

https://react-use-custom-hooks.vercel.app/

A collection of custom React hooks for managing common tasks, including useDebounce for value changes, useAsync for asynchronous operations, useForm for form state, useIsOnline for network status, and useIdle for detecting user inactivity.

Tokens
3.5K
Snippets
24
Records
26
Agent score
75%

What's inside react-use-custom-hooks

  1. Manage asynchronous operations with useAsync

    The useAsync hook manages the loading, data, and error states of an asynchronous operation (such as data fetching). It automatically handles API race conditions by ignoring responses from outdated promises if a new request has been triggered. If an operation fails, the data state will either retain the value from the previous successful call or be null.
  2. Detect user idle state with useIdle

    The useIdle hook tracks whether a user has stopped interacting with the page for a specified duration. It returns a boolean value: true if the user is idle, and false if they are active. By default, it monitors keydown, mousemove, mousedown, touchmove, touchstart, click, and scroll events.
    import { useIdle } from 'react-use-custom-hooks';
    
    function IdleExample() {
      // Detect idle state after 3000ms (3 seconds)
      const idle = useIdle(3000);
    
      return (
        <p>User is <b>{idle ? 'idle' : 'active'}</b></p>
      );
    }
  3. Detect network connectivity with useIsOnline

    The useIsOnline hook returns a boolean value indicating whether the user is currently online. The value updates automatically when the user's network status changes.

    Caveats:

    • The hook relies on navigator.onLine. A true value indicates a connection to a network, but does not guarantee actual internet access.
    • If the browser does not support navigator.onLine, the hook returns false or undefined.
    • Browser-specific behaviors: Early Chrome/Safari versions often reported true regardless of status; Desktop Firefox reports based on its "Work Offline" mode and may return true even without actual connectivity.
    import { useIsOnline } from 'react-use-custom-hooks';
    
    function ConnectionStatus() {
      const isOnline: boolean = useIsOnline();
      return <>User is online: {isOnline.toString()}</>;
    }
  4. Prevent memory leaks with useSafeState

    useSafeState is a memory-safe version of React's useState. It prevents memory leaks that occur when setState is called on an unmounted component, a common scenario during asynchronous operations like AJAX calls where a user navigates away from a page before a promise resolves. The hook checks if the component is still mounted before performing the state update; if the component has unmounted, the update is ignored. Note that this hook is slated for deprecation as React 18+ removes the misleading 'unmounted component' warning and introduces features to preserve state/DOM while disconnecting effects.
    import { useSafeState } from 'react-use-custom-hooks';
    
    function SafeStateExample() {
      const [data, setData] = useSafeState();
    
      useEffect(() => {
        setTimeout(() => {
          // This update will be ignored if the component unmounts before 3 seconds
          setData('some value');
        }, 3000);
      }, []);
    
      return <div>{data || 'loading...'}</div>;
    }
  5. Check if a component is mounted using useIsMounted

    The useIsMounted hook returns a function that can be called to determine if the component is currently mounted. This is particularly useful for avoiding memory leaks or errors when performing asynchronous operations, such as updating state or stopping API polling after a component has been unmounted.
    import { useIsMounted } from 'react-use-custom-hooks';
    
    function MyComponent() {
      const isMounted = useIsMounted();
    
      const handleAsyncAction = async () => {
        const data = await fetchData();
        if (isMounted()) {
          // Only update state if the component is still mounted
          setState(data);
        }
      };
    
      return <div onClick={handleAsyncAction}>Fetch Data</div>;
    }
  6. Manage form state and validation with useForm

    The useForm hook manages the internal state of a form and automatically tracks validation. It requires an initial state object where each key represents a field. Each field must be an object containing a value and a validator function. The validator function must return an object with isValid (boolean) and errorMessages (array of strings).

    The hook returns a tuple: [formData, setFormData].

    • formData: An object mirroring the initial state, but with isValid and errorMessages properties added to every field based on the validator's output.
    • setFormData: A change handler function that takes a field name and a new value, updates the state, and re-runs the validator for that field.
    import { useForm } from 'react-use-custom-hooks';
    
    const initialState = {
      name: {
        value: '',
        validator: (value) => {
          return value.length > 0
            ? { isValid: true, errorMessages: [] }
            : { isValid: false, errorMessages: ['Name is required'] };
        },
      },
      age: {
        value: '',
        validator: (value) => {
          if (!value) return { isValid: false, errorMessages: ['Age is required'] };
          if (value > 120) return { isValid: false, errorMessages: ['Age should be less than 120'] };
          return { isValid: true, errorMessages: [] };
        },
      },
    };
    
    function MyForm() {
      const [formData, setFormData] = useForm(initialState);
      const { name, age } = formData;
    
      // Check if the entire form is valid
      const isFormValid = Object.values(formData).every(field => field.isValid);
    
      return (
        <form>
          <input 
            value={name.value} 
            onChange={e => setFormData('name', e.target.value)} 
          />
          {name.errorMessages.length > 0 && <span>{name.errorMessages[0]}</span>}
    
          <input 
            type="number" 
            value={age.value} 
            onChange={e => setFormData('age', e.target.value)} 
          />
          {age.errorMessages.length > 0 && <span>{age.errorMessages[0]}</span>}
    
          <p>Form is {isFormValid ? 'valid' : 'invalid'}</p>
        </form>
      );
    }
  7. Debounce value changes with useDebounce

    The useDebounce hook delays the update of a value based on React state, props, or calculated values. This is typically used to prevent expensive operations (like API calls) from triggering on every keystroke during user input. The debounced value only updates after the specified delay in milliseconds has elapsed since the last change to the input value.
    import React, { useState } from 'react';
    import { useDebounce } from 'react-use-custom-hooks';
    
    function SearchComponent() {
      const [query, setQuery] = useState('');
      const delayInMilliseconds = 1000;
      
      // debouncedQuery will update 1 second after the user stops typing
      const debouncedQuery = useDebounce(query, delayInMilliseconds);
    
      return (
        <>
          <input 
            value={query} 
            onChange={e => setQuery(e.target.value)} 
            placeholder="Enter query" 
          />
          <p>Entered value: {query}</p>
          <p>Debounced value: {debouncedQuery}</p>
        </>
      );
    }
  8. Manage state with shallow merging using useLegacyState

    The useLegacyState hook mimics the behavior of this.setState from React class components. When the setState function is called, it shallowly merges the provided partial state into the current state rather than replacing it entirely. This is particularly useful when migrating class components to functional components.

    Caution: This hook does not support callbacks during initialization or within the update function.

    import { useLegacyState } from 'react-use-custom-hooks';
    
    const [state, setState] = useLegacyState({ firstName: 'John' });
    
    // Shallow merge: adds lastName while preserving firstName
    setState({ lastName: 'Doe' }); 
    // Resulting state: { firstName: 'John', lastName: 'Doe' }
  9. Manage the document title with useTitle

    The useTitle hook updates the document.title whenever the provided title value changes. It accepts a static string, a state variable, or a prop. If the restoreOnUnmount option is set to true, the hook will restore the previous document title when the component using the hook is unmounted.
    import { useState } from 'react';
    import { useTitle } from 'react-use-custom-hooks';
    
    function TitleExample() {
      const [title, setTitle] = useState('My Title!');
      
      // Updates document title dynamically
      useTitle(title);
    
      return (
        <input 
          type="text" 
          value={title} 
          onChange={e => setTitle(e.target.value)} 
        />
      );
    }
  10. Track previous props or state with usePrevious

    The usePrevious hook allows you to access the previous value of a prop, state variable, or any calculated value within a React functional component. This is useful for comparing current values with their previous versions to trigger specific side effects or UI updates.
    import { useState } from 'react';
    import { usePrevious } from 'react-use-custom-hooks';
    
    function PreviousStateExample() {
      const [count, setCount] = useState(0);
      const prevCount = usePrevious(count);
    
      return (
        <div>
          <p>Current value: <b>{count}</b></p>
          <p>Previous value: <b>{prevCount}</b></p>
          <button onClick={() => setCount(count + 1)}>++ count</button>
          <button onClick={() => setCount(count - 1)}>-- count</button>
        </div>
      );
    }
  11. Install react-use-custom-hooks

    Install the react-use-custom-hooks library using either npm or yarn.
    npm install --save react-use-custom-hooks
    # or
    yarn add react-use-custom-hooks
  12. Configure useAsync callbacks

    The options parameter for useAsync allows you to define callback functions that execute based on the outcome of the asynchronous operation.
    interface Options {
      successCallback?: () => void; // Executed on successful promise resolution
      errorCallback?: () => void;   // Executed on promise rejection
    }