use_effect

use_effect is a hook that lets you synchronize a component with an external system. It is similar to useEffect in React. An effect has 3 key parts:

  1. Effect function: The function that runs when the component is mounted, and when the dependencies change.
  2. Dependency list: A list of reactive values that the effect depends on. The effect will run when the component is mounted, and when any of the dependencies change. If a dependencies list is not provided, the effect will run after every render.
  3. Cleanup function: A function to cleanup the previous effect before the next effect function runs, or when the component is closed (unmounted). The cleanup function is optionally returned from the effect function.

Example

Recommendations

Recommendations for creating effects:

  1. Use effects to interact with an external system, such as connecting to an external server.
  2. Return a cleanup function from effects to cleanup any resources, such as disconnecting from a server.
  3. Put long-running effects on another thread to avoid blocking the render thread.
  4. Specify a dependency list to ensure the effect only runs when the dependencies change.

Connecting to an external server

Create a chat room component that connects to a server when the server URL or room ID changes. The connection is cleaned up when the component is closed. This example simply prints to the console when connecting/disconnecting from a room, rather than opening an actual connection.

Multi-threaded request

Put a long-running request on a background thread so it doesn’t block the component from updating.

Custom hooks wrapping effects

Create custom hooks that wrap effects to encapsulate functionality, such as connection to a server.

Reactive dependencies

An effect will run after the initial render (mount) and any subsequent render when a dependency has changed. The returned cleanup function will run before the next effect and when the component is closed (unmount). It is important to specify all dependencies in the dependency list to ensure the effect runs when the dependencies change.

In this example below, we connect to a server when the host or scheme changes. The effect will run when the component is mounted, and when the host or scheme is changed:

However, if we specify an empty dependency list, the effect will only run once when the component is mounted, which is probably not what we want:

If you use constant values in your effect, you can omit them from the dependency list. If the host was instead a constant outside of the component and not reactive, you can omit it from the dependency list:

If your effect doesn’t use any reactive values, its dependency list should be empty:

Examples of passing dependencies

Passing a dependency list

If you specify dependencies, the effect will run on initial render and on subsequent re-renders when the dependencies change.

In the example below, host and scheme are both reactive values that are used within the effect and cleanup functions. The effect will run when the component is mounted, and when host or scheme changes, but will not re-run when message is changed:

Passing an empty dependency list

If you specify an empty dependency list, the effect will only run once when the component is mounted, and cleanup on unmount. It will not re-run when any reactive values change.

In this example, host and scheme are hardcoded, so they are not listed as dependencies. The dependency list is empty, so the effect will only run once when the component is mounted, and cleanup on unmount:

Passing no dependency list

If you specify no dependency list, the effect will run after every single render.

In this example, the effect runs whenever host or scheme changes, but then will also run if message changes, which is probably not what you want. This is why you should usually specify the dependency list.

Removing unnecessary object dependencies

If your effect depends on an object or function that is recreated on every render, you may want to memoize it to avoid unnecessary re-renders.

To avoid this, declare the object inside the effect:

Alternatively, memoize the object using use_memo:

Removing unnecessary function dependencies

Similarly, if your effect depends on a function declared within the component, you may want to memoize it to avoid unnecessary re-renders.

To avoid this, move the function inside the effect:

Alternatively, memoize the function using use_callback: