DEV Community

Cover image for StateHub - Easy Context API for React JS
Ivan Jeremic
Ivan Jeremic

Posted on • Updated on

StateHub - Easy Context API for React JS

Everything starts with creating a new StateHub with createHub, this StateHub is everything you will ever need in your components, no other unnecessary imports!

import { createHub } from 'statehub';

export const DemoHub = createHub({
  state: { title: 'Welcome to StateHub' },
  reducer: function (state, action) {
    switch (action.type) {
      case 'CHANGE_TITLE': {
        return {
          title: 'This is the changed StateHub title.',
        };
      }
      default:
        return state;
    }
  },
  methods: {
    LogSomething: function () {
      console.log('Hello Statehub');
    },
    AlertSomething: function () {
      alert('StateHub Alert!');
    },
  },
});
Enter fullscreen mode Exit fullscreen mode

Now wrap your App with the Provider who comes with the DemoHub you created before.

As you can see the API is very clean everything you ever import is your created StateHub and nothing more.

import React from 'react';
import { DemoHub } from '../hubs/DemoHub';

export default function Index() {
  return (
    <DemoHub.Provider>
      <App />
    </DemoHub.Provider>
  );
}
Enter fullscreen mode Exit fullscreen mode

Now you can use the state in your component.

And again you can see, everything you need is coming from your created StateHub, no other imports are required except your DemoHub.

import React from 'react';
import { DemoHub } from '../hubs/DemoHub';

function App() {
  const [state, dispatch, methods] = DemoHub.use(); // call .use() to use the state.

  return (
    <div>
      <h2>{state.title}</h2>
      <button onClick={() => dispatch({ type: 'CHANGE_TITLE' })}>
        Change Title
      </button>

      <h2>Method Example 1:</h2>
      <button type='button' onClick={methods.LogSomething}>
        Log something to the console
      </button>

      <h2>Method Example 2:</h2>
      <button type='button' onClick={methods.AlertSomething}>
        Trigger alert
      </button>
    </div>
  );
}

export default App;
Enter fullscreen mode Exit fullscreen mode

state & reducer is optional that means you can create StateHub's with methods only and retrieve them directly where needed by calling YourHub.methods().

import React from 'react';
import { DemoHub } from '../hubs/DemoHub';

function App() {
  const { LogSomething, AlertSomething } = DemoHub.methods();

  return (
    <div>
      <h2>Method Example 1:</h2>
      <button type='button' onClick={LogSomething}>
        Log something to the console
      </button>

      <h2>Method Example 2:</h2>
      <button type='button' onClick={AlertSomething}>
        Trigger alert
      </button>
    </div>
  );
}

export default App;
Enter fullscreen mode Exit fullscreen mode

You can use as many StateHubs as you want.

import React from 'react';
import App from '../components/App';
import { AuthHub, DatabaseHub, ResponsiveHub, ModalHub } from '../hubs/DemoHub';

export default function Index() {
  return (
    <AuthHub.Provider>
      <DatabaseHub.Provider>
        <ResponsiveHub.Provider>
          <ModalHub.Provider>
            <App />
          </ModalHub.Provider>
        </ResponsiveHub.Provider>
      </DatabaseHub.Provider>
    </AuthHub.Provider>
  );
}
Enter fullscreen mode Exit fullscreen mode

Support for Class Components:

To support React < 16.8.0, where the Context needs to be consumed by class
components here the render-prop based API for context consumers:

import React from 'react';
import { DemoHub } from '../hubs/DemoHub';

class App extends React.Component {
  render() {
    return (
      <DemoHub.Consumer>
        {(state, dispatch, methods) => (
          <div>
            <h2>{state.title}</h2>
            <button onClick={() => dispatch({ type: 'CHANGE_TITLE' })}>
              Change Title
            </button>

            <h2>Method Example 1:</h2>
            <button type='button' onClick={methods.LogSomething}>
              Log something to the console
            </button>

            <h2>Method Example 2:</h2>
            <button type='button' onClick={methods.AlertSomething}>
              Trigger alert
            </button>
          </div>
        )}
      </DemoHub.Consumer>
    );
  }
}
Enter fullscreen mode Exit fullscreen mode

Discussion (0)