WHAT IS REDHOOKS?

Redhooks is a tiny library for holding a predictable state container within your React applications. Inspired by Reduxjs, 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



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



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



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



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

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

App Component

./components/App.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



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!



Other Sandbox Examples

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

Shopping Cart: CodeSandbox

TodoMVC: CodeSandbox

Tree-View: CodeSandbox

Saga-Middleware: CodeSandbox

Conclusion

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