Redhooks: predictable state container for React applications.
Tags: react, hooks, javascript, webdev
Published: 2019-01-21 08:39:53

---
title: Redhooks: predictable state container for React applications.
published: true
description: A tiny library for holding a predictable state container within your React applications.
tags: react,hooks,javascript,webdev
---

<a href="https://github.com/iusehooks/redhooks"><img src="https://raw.githubusercontent.com/iusehooks/redhooks/master/logo/logo.png" width="224" height="61" alt="Redhooks Repository" /></a>

# WHAT IS REDHOOKS?

[Redhooks](https://github.com/iusehooks/redhooks/) is a tiny library for holding a predictable state container within your React applications. Inspired by [Reduxjs](https://redux.js.org/), it reimplements Redux’s API using the experimental Hooks API and the Context API. It supports the use of middleware like redux-thunk, redux-saga or your custom middleware conforming to the middleware's API.

Let's start to write our first simple application by using redhooks.

### Reducer

A reducer is a pure function that takes the previous state and an action which is a plain object, and returns the next state.

`./reducer.js`

```javascript
import { combineReducers } from "redhooks";

const greeting = (state = "good morning", { type, payload }) => {
  switch (type) {
    case "GREET":
      state = payload;
      return state;
    default:
      return state;
  }
};

const counter = (state = 0, { type, payload }) => {
  switch (type) {
    case "INCREMENT":
      return state + 1;
    case "DECREMENT":
      return state - 1;
    default:
      return state;
  }
};

const rootReducer = combineReducers({ greeting, counter });
export default rootReducer;
```

### Store

A store holds the whole state tree of your application. The state within a store is read only, the only way to change the state is to dispatch an action. To create a store we need to  pass our root reducing function to `createStore(reducer, [opts])`.

`./store.js`

```js
import { createStore } from "redhooks";
import rootReducer from "./reducers";

const opts = {
  preloadedState: { counter: 1 },
  initialAction: { type: "INCREMENT" }
};
const store = createStore(rootReducer, opts);

export default store;
```

### Counter - Function Component

Within function components in order to access the store we can use the `useStore()` redhooks API. This returns an object with props that are the state object and the dispatch function.

`./components/Counter.js`

```js
import React from "react";
import { useStore } from "redhooks";
const Counter = () => {
  const { state, dispatch } = useStore();
  const { counter } = state;
  return (
    <div>
      <h1>{counter}</h1>
      <button onClick={() => dispatch({ type: "INCREMENT" })}> + </button>
      <button onClick={() => dispatch({ type: "DECREMENT" })}> - </button>
    </div>
  );
};
export default Counter;
```

### Greeter - Class Component

Within a class component due to the fact that React Hooks are not allowed, we need to use the `connect` redhooks API which connects either Class or Function Components to the redhooks store

`./components/Greeter.js`

```js
import React, { Component } from "react";
import { connect } from "redhooks";
class Greeter extends Component {
  render() {
    const { greeting, dispatch } = this.props;
    return (
      <div>
        <h1>{greeting}</h1>
        <button onClick={() => dispatch({ type: "GREET", payload: "HELLO" })}>
          say hello
        </button>
        <button onClick={() => dispatch({ type: "GREET", payload: "GOODBYE" })}>
          say goodbye
        </button>
      </div>
    );
  }
}
const mapStateToProps = state => ({ greeting: state.greeting });
export default connect(mapStateToProps)(Greeter);
```
Using the **mapStateToProps** method we can subscribe any components to the redhooks store. Any time the store is updated, **mapStateToProps** will be called and it's results, which must be a plain object, will be merged into your component's props. In the example above two props are injected, greeting and dispatch.

> We could have avoid to use the `connect` for the Greeter Class Component. It was only used for showing how it works. You can get more details on why and when it should be used at [redhooks docs] (https://github.com/iusehooks/redhooks/#connect)

Now let's put all together and render our tiny application.

### App Component

`./components/App.js`

```js
import React from "react";
import Counter from "./Counter";
import Greeter from "./Greeter";

const App = () => (
  <div>
    <Counter />
    <Greeter />
  </div>
);

export default App;
```

### Render the application

`./index.js`

```js
import React from "react";
import { render } from "react-dom";
import Provider from "redhooks";

import store from "./store";
import App from "./components/App";

render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById("root")
);
```

We are done! A live codesandbox example for you to play with!
{% codesandbox jnxvow5wyw %}

### Other Sandbox Examples

Following few open source projects implemented with redux have been migrated to redhooks:

Shopping Cart: [CodeSandbox](https://codesandbox.io/s/5yn1258y4l)
TodoMVC: [CodeSandbox](https://codesandbox.io/s/7jyq991p90)
Tree-View: [CodeSandbox](https://codesandbox.io/s/rmw98onnlp)
Saga-Middleware: [CodeSandbox](https://codesandbox.io/s/48pomo7rx7)

## Conclusion

Hope you enjoyed reading this post. If you did, please checking out the redhooks repo, or even better contribute to redhooks. Thanks.

{% github https://github.com/iusehooks/redhooks %}