React with Redux, Tailwind and More
Intro
React is currently the most popular front end framework. We will set up a react project and use Vite for tooling and packaging, Redux for managing state of the application and Tailwind CSS for styling the UI.
NOTE: I might update this post from time to time with info about more packages
Create project
NOTE: We will use Bun to install and manage packages. These steps will also work for other similar package managers like NPM or PNPM. Check out their installation guides on their respective websites
Setup a new project with create-vite
. When prompted select React
framework and Typescript + SWC
variant
% bunx create-vite <name>
✔ Select a framework: › React
✔ Select a variant: › TypeScript + SWC
Change directory to the project folder and run
% bun install
This will add the dependencies needed for React and Typescript.
NOTE: The next step is not required. Revert the changes if you get build errors using bun
Since we are using Bun, we can modify the package.json and add --bun
flag to dev, build and preview scripts to run the Vite CLI using bun
instead of node
Ref: https://bun.sh/guides/ecosystem/vite
{
"scripts": {
"dev": "bunx --bun vite",
"build": "tsc && bunx --bun vite build",
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
"preview": "bunx --bun vite preview"
},
}
We can now run the above scripts with bun run <script_name>
We can now make changes to the project files. Run bun run dev
to start the development mode. Go to the URL int the output to see the default project. Change the site title in index.html file. Live reload should automatically update it on the website.
Add TailwindCSS
Vite has build in support for PostCSS, so we will use Tailwind as a PostCSS plugin.
Ref: https://vitejs.dev/guide/features#postcss
Ref: https://tailwindcss.com/docs/guides/vite#react
% bun install -D tailwindcss postcss autoprefixer
We also need to initialize Tailwind and PostCSS configuration files. This step will create two files in the project directory, one for Tailwind and one for PostCSS
% bunx tailwindcss init -p
Created Tailwind CSS config file: tailwind.config.js
Created PostCSS config file: postcss.config.js
The command above automatically sets tailwind
and autoprefixer
plugins in PostCSS config file
We do, however, need to make changes to Tailwind config file to tell it where the CSS utility classes will be used in our project. We can add the index.html file and all files in the src directory in the content section of tailwind.config.js
content: [
"./index.{js,ts,jsx,tsx}",
"./src/**/*.{js,ts,jsx,tsx}",
],
At this point the complete tailwind.config.js file should look like
/** @type {import('tailwindcss').Config} */
export default {
content: [
"./index.{js,ts,jsx,tsx}",
"./src/**/*.{js,ts,jsx,tsx}",
],
theme: {},
plugins: [],
}
Now we add the Tailwind import directives in our index.css
@tailwind base;
@tailwind components;
@tailwind utilities;
NOTE: We can remove the unused CSS in index.css and src/App.css
Add Redux
Redux Toolkit is currently the recommended way to use Redux in React projects. Let’s add the required packages
% bun install @reduxjs/toolkit react-redux
Create a directory called state under src. We will use this directory to keep files related to state.
We can create a state store which will keep the state of our application. Create a new file src/state/store.ts with the following contents
import { configureStore } from '@reduxjs/toolkit';
export const store = configureStore({
reducer: {},
});
export type RootState = ReturnType<typeof store.getState>;
export type AppDispatch = typeof store.dispatch;
This will configure our store and create the types for accessing state and dispatching events.
NOTE: This is an empty store with no state or actions. Depending on our project requirements, we will add reducers and actions (not covered in this post). Check out some of my project posts for them.
Now, we need to warp our App
component with Redux state provider so that the state is accessible anywhere in our application. In src.main.tsx add imports
import { Provider } from 'react-redux'
import { store } from './state/store'
and change
ReactDOM.createRoot(document.getElementById('root')!).render(
<React.StrictMode>
<App />
</React.StrictMode>,
)
to
ReactDOM.createRoot(document.getElementById('root')!).render(
<React.StrictMode>
<Provider store={store}>
<App />
</Provider>
</React.StrictMode>,
)
Now we can access state (eg. some_reducer.some_state) anywhere in our application using
import { useSelector } from "react-redux";
import { RootState } from "./state/store";
const x = useSelector((state: RootState) => state.some_reducer.some_state);
We can also dispatch actions (eg. some_action from someSlice) using
import { useDispatch } from "react-redux";
import { AppDispatch } from "./state/store";
import { some_action } from "./state/someSlice";
const dispatch = useDispatch<AppDispatch>();
dispatch(some_action());
Optional packages
Font Awesome
If we need to add fonts from Font Awesome, we can add the core svg and react component packages
bun install @fortawesome/fontawesome-svg-core @fortawesome/react-fontawesome@latest
Then we can add the icon bundles we need
bun install @fortawesome/free-solid-svg-icons
bun install @fortawesome/free-regular-svg-icons
bun install @fortawesome/free-brands-svg-icons
The above steps can all be done at the same time with
bun install @fortawesome/fontawesome-svg-core @fortawesome/react-fontawesome@latest @fortawesome/free-solid-svg-icons @fortawesome/free-regular-svg-icons @fortawesome/free-brands-svg-icons
Then we can import individual icons and use them whenever needed
sample.tsx
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faQuoteLeft } from "@fortawesome/free-solid-svg-icons";
function Sample() {
return <FontAwesomeIcon icon={faQuoteLeft} />
}