DEV Community

Cover image for Reuse React hooks in state sharing
Slava Birch
Slava Birch

Posted on • Edited on

9 1

Reuse React hooks in state sharing

Hi guys, today I'm going to talk about how to complete your code with one hook that will complete the puzzle!

The release of React 16.8 was a gift and a blessing, hooks were a great tool for managing the state of components. And having met with amicability, the community began to create new hooks based on standard ones for asynchronous operations, for interacting with external logic, and many many others.

Hooks let you use state and other React features without writing a class.
You can also build your own Hooks to share reusable stateful logic between components. (React website)

But (I'm sure) it became a chagrin for everyone that hooks can only store data at the component level. And therefore components can share their state only with children.

And that's the problem.

We have enough hooks to describe any logic, but there is no way to use their state together between a group of unrelated components.

You can see that Recoil, Redux, MobX, and the standard React hooks do the same thing - managing reactive state.
But why do we need to use in our applications a way of describing logic on hooks in components and on an external application state management system?

I suggest you try the simplest way to share the state described in hooks with other unrelated components on the page.

useBetween

And this is just one hook, with the only one call argument - a custom hook, the result of which will be shared by everyone.

For example, let's describe a custom hook that supplies a hash from the browser's address bar. The hook subscribes to changes to the browser hash through the window event.

// router.shared.ts
import { useState, useCallback, useEffect } from "react";
import { useBetween } from "use-between";

const useRouter = () => {
  const [hash, setHash] = useState("");

  const syncHash = useCallback(() => {
    setHash(window.location.hash);
  }, [setHash]);

  useEffect(() => {
    syncHash();
    window.addEventListener("hashchange", syncHash);
    return () => {
      window.removeEventListener("hashchange", syncHash);
    };
  }, [syncHash]);

  return {
    hash
  };
};

export const useSharedRouter = () => useBetween(useRouter);
Enter fullscreen mode Exit fullscreen mode

In the last line of the example, we used a call to useBetween passing a custom useRouter hook as an argument, and thus created a new useSharedRouter hook - a shared router for all components that will use it.

const Hash = () => {
  const { hash } = useSharedRouter();
  return (
    <p>Location hash: {hash}</p>
  )
}

export const App = () => (
  <>
    <Hash />
    <Hash />
    <Hash />

    <a href="#hash-1">hash-1</a>
    <a href="#hash-2">hash-2</a>
  </>
)
Enter fullscreen mode Exit fullscreen mode

Edit Counter with useBetween

In this example, the router will be created once and will be used for all the Hash components. Every time the hash of the navigation bar address changes, all components using useSharedRouter will be updated!

We used the standard React hooks that are familiar and understandable to everyone to create a shared state between any components using just one external hook useBetween.

Everything will be installed simply npm i use-between and you can use and enjoy, and for my taste, the easiest way to share the state in React!

If you like this idea and would like to use it, please put star in github. It will be your first contribution!

GitHub logo betula / use-between

Sharing state between React components

use-between

npm version build status npm bundle size code coverage typescript supported 100k+ downloaded

When you want to separate your React hooks between several components it's can be very difficult, because all context data stored in React component function area If you want to share some of state parts or control functions to another component your need pass It thought React component props. But If you want to share It with sibling one level components or a set of scattered components, you will be frustrated.

useBetween hook is the solution to your problem 😚

import React, { useState, useCallback } from 'react';
import { useBetween } from 'use-between';
const useCounter = () => {
  const [count, setCount] = useState(0);
  const inc = useCallback(() => setCount(c => c + 1), []);
  const dec = useCallback(() => setCount(c
Enter fullscreen mode Exit fullscreen mode

Heroku

Built for developers, by developers.

Whether you're building a simple prototype or a business-critical product, Heroku's fully-managed platform gives you the simplest path to delivering apps quickly — using the tools and languages you already love!

Learn More

Top comments (0)

Cloudinary image

Optimize, customize, deliver, manage and analyze your images.

Remove background in all your web images at the same time, use outpainting to expand images with matching content, remove objects via open-set object detection and fill, recolor, crop, resize... Discover these and hundreds more ways to manage your web images and videos on a scale.

Learn more

👋 Kindness is contagious

If this article connected with you, consider tapping ❤️ or leaving a brief comment to share your thoughts!

Okay