loading...
Cover image for StateHub - Easy Context API for React JS

StateHub - Easy Context API for React JS

ivanjeremic profile image Ivan Jeremic ・2 min read

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!');
    },
  },
});

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>
  );
}

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;

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;

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>
  );
}

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>
    );
  }
}

Discussion

pic
Editor guide