The new hooks proposal for react component looks great, the syntax looks very clean and readability is great. Over the last weekend I decided to give it a try and build a simple budgeting app.

Budgeting app with React + Redux + Hooks + Tailwind

To speed things up, I decided to use Create React App to get up and running in minutes. Given that my time for coding on weekends is very limited, I decided to use tailwind for the styles, a tool that I’ve been wanting to use for a while.

Integrating Tailwind CSS

Integrating tailwind with CRA is quite easy, simply install the library and create a couple scripts to compile it for you.

$ yarn add tailwindcss --dev

$ yarn add postcss-cli --dev

$ yarn add autoprefixer --dev

Once you have the dependencies ready, you need to initialize tailwind like this:

$ ./node_modules/.bin/tailwind init

This will create a configuration file in the root directory. You can configure here the colors, sizing, fonts, etc. In my case I left the default configuration only because I was in a hurry (I can only code in weekends when my baby is sleeping 😅). But will come back to tweak it and make the final bundle smaller.

We also need to configure postcss, we basically need to add tailwind as a plugin.

const tailwindcss = require('tailwindcss'); module.exports = {

plugins: [

tailwindcss('./tailwind.js'),

],

};

Given that I’m using CRA, I don’t have full access to the webpack config (Unless we hack around), otherwise instead of using postcss we can use the webpack loader for tailwind.

In order to use tailwind in React, we need to create a css file and import the preflight and utilities. The file can by defined anywhere, in my case is under src/theme/base.css

@tailwind preflight;

@tailwind utilities; /* Your custom CSS here */

The last thing we need to do is compile the css and use it in our react app. We need to add the following tasks inside package.json

"build:css": "postcss src/theme/base.css -o src/index.css",

"watch:css": "postcss src/theme/base.css -o src/index.css -w"

The first task is taking the base css file and compiling it into src/index.css , this is the file we need to import into our react app.

The second task is optional, in case you want watch any changes into the base css file, useful for development.

Now we need build the css before using it, we can do it manually but I think it will be easier to just do it before starting webpack.

"start": "npm run watch:css && react-scripts start",

Finally, we need to import the compiled file into our React components.

import React from 'react';

import ReactDOM from 'react-dom';

import { StoreProvider } from 'redux-react-hook';

import App from './containers/App';

import store from './store';

import { setAppUpdated } from './store/modules/app/actions';

import * as serviceWorker from './serviceWorker'; import './index.css'; // <---- Here!! ReactDOM.render(

<StoreProvider value={store}>

<App />

</StoreProvider>,

document.getElementById('root')

);

// unregister() to register() below. Note this comes with some pitfalls.

// Learn more about service workers:

serviceWorker.register({

onUpdate: () => store.dispatch(setAppUpdated()),

}); // If you want your app to work offline and load faster, you can change// unregister() to register() below. Note this comes with some pitfalls.// Learn more about service workers: http://bit.ly/CRA-PWA serviceWorker.register({onUpdate: () => store.dispatch(setAppUpdated()),});

That’s all, now we can use tailwind in our react components! It’s really awesome to build UIs without writing any css!

Take a look at my Panel component, super easy to build! I didn’t have to write a single line of CSS code:

import React from 'react'; export default function Panel({ children, title }) {

return (

<div className="bg-white py-8 px-4 border-t-4 border-orange"

{title && <h3 className="mb-4">{title}</h3> }

{children}

</div>

);

}

A panel component build with Tailwind!

Using React hooks with Redux

There’s already a discussion on how to implement hooks for redux, very interesting approaches indeed. However, at this point the official redux project doesn’t support hooks.

There are a couple projects that help you to access the redux state with hooks, one of my favorites is redux-react-hook. I liked because it gives you access to the state by defining a mapping function, similar to the one we use in connect and it also gives you access to the dispatch method to fire actions.

The first thing we need to do is remove the official redux provider and use the provider in this library.

import { StoreProvider } from 'redux-react-hook';

import store from './store'; ReactDOM.render(

<StoreProvider value={store}>

<App />

</StoreProvider>,

document.getElementById('root')

);

In order to access the state inside of your React component, you need to use the useMappedState function, this receives a mapping function and returns an object containing the data you need.

import React from 'react';

import { useMappedState } from 'redux-react-hook';

import { getLatestGroupedByDate } from 'store/modules/transactions/selectors'; const mapState = state => ({

latest: getLatestGroupedByDate(state),

}); export default function Dashboard() {

const { latest } = useMappedState(mapState); return (

<span>{latest.length} Transactions</span>

);

}

The mapState function is exactly the same as the one we use in connect , it’s important to declare this function outside of the react component, otherwise it will be created on every render.

If we need to use props inside the mapState then we can move it inside the component, but we will have to use useCallback in order to memoize it and avoid re-creating it on every render.

By calling the useMappedState we can retrieve the data that we need from the redux store! The syntax using hooks looks really clean, easy to read and understand. We don’t need HOCs anymore 🎉!

Now, in order to dispatch actions, all we need to do is call the hook useDispatch and it will return the dispatch method from the store! From there you can basically fire any action you want, for example:

import { useDispatch } from 'redux-react-hook'; export default function AddTransaction({ isExpense }) {

const [amount, setAmount] = useState(0);

const dispatch = useDispatch();

const saveTransaction = useCallback(

dispatch(postTransaction({ amount }))

, [amount]); return (

<button onClick={saveTransaction}>Save</button>

);

}

The important thing here is the use of useCallback , this is needed to avoid creating the inner action on every render, it will only be created when the amount gets updated.

Conclusion

By using hooks you can see how easy is to access the state as well as dispatching actions. I really liked the way hooks play with redux and I think this is a step forward lowering the bar for new devs.

Using tailwind is really awesome! I enjoyed building an app without writing any css, truly amazing!

You can see the app running and if you are interested in the code you should check my repo.