Thursday, July 24, 2025

React Application Using Vite

 




In recent years it seems that Vite is replacing the old known create-react-app. I've gave it a try, and it is working great. By comparison to create-react-app, it is faster and has a better flexible configuration preventing the need the eject. Listed below are the basic steps to create a react-redux application including CSS modules and async thunk requests.


Installation


To start we need to have a recent NPM & Node installed, so we better update it using NVM:


nvm install --lts


Next we run the command to create our new project:


npm create vite@latest


And we follow the instructions until the project is created, and we can run it:

cd my-vite
npm install
npm run dev


We add the redux support:

npm install -S @reduxjs/toolkit react-redux


And we can start the development.


Framework Code


We create the redux main store (it includes import to the component that we will add later).


store.jsx

import {configureStore} from '@reduxjs/toolkit'

import box from "./component/box/slice.jsx"

export const store = configureStore({
middleware: (getDefaultMiddleware) => getDefaultMiddleware({
immutableCheck: {ignoredPaths: ['graph']},
serializableCheck: {ignoredPaths: ['graph']},
}),
reducer: {
box,
},
})

export default store


We import this store in our main code.


main.jsx

import {StrictMode} from 'react'
import {createRoot} from 'react-dom/client'
import './index.css'
import App from './App.jsx'
import {Provider} from 'react-redux'
import store from './store'

createRoot(document.getElementById('root')).render(
<StrictMode>
<Provider store={store}>
<App/>
</Provider>
</StrictMode>,
)


We update the application to include our new component (again we will descibe it later).


App.jsx

import {useState} from 'react'
import './App.css'
import Box from "./component/box/component.jsx";

function App() {
const [count, setCount] = useState(0)

return (
<>
<div className="card">
<button onClick={() => setCount((count) => count + 1)}>
count is {count}
</button>
</div>
<Box
name="my-box"
/>
</>
)
}

export default App


The last thing to do it to add wrapper for calling to APIs.


request.jsx


export async function sendRequest(url, body) {
let fetchOptions = {
method: 'post',
headers: {
'Content-type': 'application/json',
},
body: JSON.stringify(body),
}

const response = await fetch(url, fetchOptions)

if (response.status === 200) {
const json = await response.json()
return {
ok: true,
response: json,
}
}

let error = await response.text()
try {
const parsed = JSON.parse(error)
if (parsed.message) {
error = parsed.message
}
} catch (e) {
// ignore - send the actual error text
}

return {
ok: false,
response: error,
}
}


Application Code


The last thing to do it to add our box component which like most components includes 3 files: the component GUI, the redux slice, and the CSS module.


component.jsx

import React from 'react'
import {useDispatch, useSelector} from 'react-redux'
import {selectState, updateBox, updateMyData} from './slice'
import styles from './component.module.css'


function Box(props) {
const {name} = props
const dispatch = useDispatch()
const state = useSelector(selectState)
const {boxWidth} = state

function clickHandler() {
dispatch(updateBox({doubleClick: false}))
}

function doubleClickHandler() {
dispatch(updateMyData())
dispatch(updateBox({doubleClick: true}))
}

const dynamicStyle = {
width: `${boxWidth}px`,
}

return (
<div
className={styles.boxStyle}
onClick={clickHandler}
onDoubleClick={doubleClickHandler}
style={dynamicStyle}
>
{name}
</div>
)
}

export default Box


component.module.css


.boxStyle{
background: blue;
color: yellow;
font-size: large;
font-weight: bold;
}


slice.jsx

import {createAsyncThunk, createSlice} from '@reduxjs/toolkit'
import {sendRequest} from "../request/request.jsx";


const initialState = {
boxWidth: 100,
}


export const updateMyData = createAsyncThunk(
'box/updateMyData',
async (input, thunkApi) => {
const state = thunkApi.getState()
const {box} = state
const {boxWidth} = box
const body = {
WIDTH: boxWidth,
}
const {response, ok} = await sendRequest('http://localhost:3000/my-api', body)

if (!ok) {
console.error(response)
return
}

console.log(response)
},
)

export const slice = createSlice({
name: 'box',
initialState,
reducers: {
updateBox: (state, action) => {
const {doubleClick} = action.payload
if (doubleClick) {
state.boxWidth = 100
} else {
state.boxWidth += 100
}
},
},
})

export const {updateBox} = slice.actions

export const selectState = (state) => state.box


export default slice.reducer


Final Note


I recommend using Vite since it is much faster and the result transpiled code works faster. It is alos a living project unlike the create-react-app which seems near death.


No comments:

Post a Comment