Using Hooks

To help make components easier to re-use and simpler to understand, React and the React ecosystem have been trending towards functional components and hooks. Hooks are a convenient way to add state and side-effects to functional components. They also provide a convenient way for libraries to expose behavior.

While we are generally in favor of hooks, we have some recommendations about how hooks should be used with the Sentry front-end.

Using hooks from libraries

If a library provides hooks you should use them. Often this will be the only way to consume a library. For example dnd-kit exposes all of its primitives via hooks and we should use the library the way it was intended to be used.

We don't prefer libraries that use or don't use hooks. Instead favor libraries with cleaner, simpler APIs, and smaller bundle sizes over ones with larger more complex APIs or larger bundle sizes.

Using react's built-in hooks

The useState, useMemo, useCallback, useContext, and useRef hooks are welcome in any functional component. They are generally a good choice in presentational components that need a small amount of state, or access to react primitives like references and context. For example, a component with a slide-out or expandable state.

The useEffect hook is more complex and you need to be careful to track your dependencies and ensure that subscriptions are canceled through a cleanup callback. Complex chained applications of useEffect should be avoided and 'controller' components should remain class-based at this time.

Likewise, the useReducer hook overlaps with state-management which currently has an undecided future. We would like to avoid yet another state management pattern, so at this time avoid useReducer.

Using context

As we plan our path away from Reflux, the useContext hook provides a simpler implementation option to share state and behavior. When you need to create new sources of shared state, consider using context and useContext instead of Reflux. Additionally the wormhole state management pattern can be leveraged to expose shared state and mutation functions.

Using custom hooks

Custom hooks can be created to share reusable logic in the application. When creating a custom hook, the function name must follow the convention, starting with "use" (useTheme, for example) and it's fine to call other hooks inside of custom hooks.

Be aware of the rules and caveats of hooks

React hooks have a few rules. Be aware of the rules and limitations that hooks create. We use the ESLint rules to prevent most of the hook rules from being trespassed.

Additionally, we recommend keeping your usage of the useEffect to a minimum. Using multiple useEffect callbacks indicates that you have a component that is highly stateful and that you should be using a class component instead.

Our foundations are still class-based

Our foundational view components (AsyncView and AsyncComponent) are class-based and will be for a long time. Keep this in mind as you build views. You'll need additional wrapper components to access hooks or convert hook state into props for your AsyncComponent.

Don't rewrite for hooks

While hooks can be ergonomic in new code we should avoid rewriting existing code to leverage hooks. Rewriting takes time, exposes us to risk and provides very little end-user value.

If you need to rework a component to consume hooks from a library, then also consider converting from a class to a function component.

You can edit this page on GitHub.