Melody Documentation
  • Why Melody?
  • Quickstart
    • What is Melody?
    • Tutorial
    • Installation
  • Templates
    • Twig
    • Mounting Components
    • Keys and Loops
    • Attributes
    • CSS Classes
    • Inline Styles
    • Refs
    • CSS Modules
  • Melody-Streams
    • Basic concept
    • A Step-by-Step Walkthrough
  • MELODY-STREAMS API
    • createComponent
    • The component function
  • melody-hooks
    • Overview
    • Rules of Hooks
    • Event Handling
    • Separation of Concerns
  • melody-hooks API
    • useState
    • useAtom
    • useEffect
    • useRef
    • useCallback
    • useMemo
    • useReducer
    • usePrevious
  • melody-component
    • Overview
  • melody-hoc
    • Overview
Powered by GitBook
On this page
  • Execute a side effect when needed
  • Execute a side effect on mount and unmount
  • Use a side effect on mount, every render and unmount

Was this helpful?

  1. melody-hooks API

useEffect

The useEffect hook serves a the primary way for handling side effects in a Melody component.

It allows you to execute code when,

  • it is mounted

  • it is updated

  • it is unmounted (removed)

Execute a side effect when needed

useEffect(sideEffectFunction, cacheKeyProperties[])

The most common form of useEffect accepts a function, the side effect you want to execute, and an array of variables it depends on. Those cacheKeyProperties are used to determine whether to execute the side effect again or not.

// we'll create a reusable data loading hook for items
function useItemData({ itemId }) {
    // use an atom to store the data
    const [getData, setData, data] = useAtom({});
    // this hook will be executed after the component has been mounted
    // and it will only be executed again if the itemId changes
    useEffect(() => {
        // ceremony to get a URL and setup an abortable fetch
        const url = getItemDataUrl(itemId);
        
        const controller = new AbortController();
        const signal = controller.signal;
        
        fetch(url, { signal }).then(response => {
          return response.json();
          // finally update the data
        }).then(setData);
        // this function is executed when
        // 1. the component is unmounted or
        // 2. the itemId changes
        // we'll use it to cancel the request if its still running
        return () => controller.abort();
    }, [itemId]);
    return [ getData, data ];
}

The above example is trying to be realistic by also showing how you'd need to abort a request that is no longer useful. For that, it relies on the abortable fetch API which is not yet as widely spread as the original fetch API. You might need an additional polyfill to make it work.

However, the concept itself also lends itself very nicely towards usage with Rx.js which comes with an abortable ajax utility.

Execute a side effect on mount and unmount

useEffect(sideEffectFunction, [])

When given an empty array the side effect will never be evaluated again, as the cache key never changes. This gives a chance to build a side effect that executes when the component mounts and unmounts.

function useDocumentTitle(title) {
    useEffect(() => {
        // executed after component was mounted
        const oldTitle = document.title;
        document.title = title;
        // executed when the component is unmounted
        return () => document.title = oldTitle;
    }, []);
};

The above example is actually not a good one since you'd really want to re-evaluate the side effect when the title changes.

Use a side effect on mount, every render and unmount

useEffect(sideEffectFunction)

You can also omit the cacheKeyProperties array entirely if you want to create a side effect that executed every time the component is rendered.

function useSlowDeviceKiller() {
    useEffect(() => {
        // executed on component mount and every single render
        fibonacci(10);
        // this function will be executed on _every render_ before
        // the side effect is re-evaluated
        return () => fibonacci(7);
    });
}

While technically feasible you most likely won't need this variant. It is a performance disaster waiting to happen.

We strongly advise that if you do really need it, you accompany it with some documentation on why you decided to go that route to help your colleagues avoid introducing issues later on.

PrevioususeAtomNextuseRef

Last updated 6 years ago

Was this helpful?