Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I share state data between components using custom hooks?

I have the following custom hook called useFlash:

import { useState } from 'react';


export default function useFlash() {
  const [messages, setMessages] = useState([]);

  const showFlash = (message: string) => {
    setMessages([...messages, message]);
  };

  const clearMessage = (index: number) => {
    setMessages(messages.filter((_m, i) => index !== i));
  };

  return {
    messages,
    showFlash,
    clearMessage
  };
}

Then I have this HOC providing it to two other components:

import React from 'react';
import useFlash from '../effects/useFlash';

const withFlash = (WrappedComponent: React.Component) => {
  const WithFlash = () => {
    const { messages, showFlash, clearMessage } = useFlash();

    return (
      <WrappedComponent
        messages={messages}
        showFlash={showFlash}
        clearFlashMessage={clearMessage}
      />
    );
  };

  return WithFlash;
};

export default withFlash;

It works well, except each use of the HOC gets its own state data. I need the state to be global. I know I can use contexts with consumer/providers, but I thought this way would be a little simpler. It is not proving to be true, is there a way to make this global?

like image 598
Brandon Avatar asked Mar 04 '19 08:03

Brandon


Video Answer


1 Answers

You'll need to use Context, but it's not that bad..

create your context..

import React, { useState } from 'react';

export const FlashContext = React.createContext();

export const FlashProvider = ({ children }) => {
  const [messages, setMessages] = useState([]);
  return (
    <FlashContext.Provider value={{ messages, setMessages }}>
      {children}
    </FlashContext.Provider>
  );
};

wrap your components in the provider somewhere higher in the tree..

import React from "react";
import { FlashProvider } from "./flash-context";

const App = () => <FlashProvider><TheRest /></FlashProvider>;

export default App;

then use the context in your custom hook..

import React, { useContext } from "react";
import { FlashContext } from "./flash-context";

export default function useFlash() {
  const { messages, setMessages } = useContext(FlashContext);

  const showFlash = (message) => {
    setMessages([...messages, message]);
  };

  const clearMessage = (index) => {
    setMessages(messages.filter((_m, i) => index !== i));
  };

  return {
    messages,
    showFlash,
    clearMessage
  };
}
like image 67
lecstor Avatar answered Oct 09 '22 16:10

lecstor