Cheatsheet - Setup Redux-toolkit with Laravel and Next.js

Nav • February 27, 2022

react nextjs laravel

Here is a cheatsheet for setting up Redux toolkit with Next.js on the frontend, and Laravel api on the backend. The Next.js frontend is a clone Laravel Breeze Next.js Edition. Laravel is a basic install with Laravel Breeze.

Frontend contains all the auth pages you've come to expect from Laravel Breeze package.

More info:
github.com/laravel/breeze-next
redux-toolkit.js.org
nextjs.org

Frontend: Next.js

# Clone starter repo
git clone git@github.com:laravel/breeze-next.git next-frontend

cd next-frontend

# Copy env variables
cp .env.example .env.local

npm install

# Start dev server
npm run dev

Backend: Laravel Breeze

# Create the Laravel application...
laravel new next-backend

cd next-backend

# Install Breeze and dependencies...
composer require laravel/breeze

php artisan breeze:install api

# Setup and configure your database settings...
php artisan migrate

# Serve the application...
php artisan serve

Setup Redux-toolkit for state management

# cd into your frontend project
npm install @reduxjs/toolkit react-redux
// Create a file: src/app/store.js
import { configureStore } from '@reduxjs/toolkit'
import counterReducer from '../features/counter/counterSlice'

export const store = configureStore({
    reducer: {
        counter: counterReducer,
    },
})
// Update pages/_app.js
import { store } from '../app/store'
import { Provider } from 'react-redux'

const App = ({ Component, pageProps }) => {
    return (
        <Provider store={store}>
            <Component {...pageProps} />
        </Provider>
    )
}
// Create a slice in: src/features/counter/counterSlice.js
import { createSlice } from '@reduxjs/toolkit'

const initialState = {
    value: 0,
}

export const counterSlice = createSlice({
    name: 'counter',
    initialState,
    reducers: {
        increment: state => {
            state.value += 1
        },
        decrement: state => {
            state.value -= 1
        },
        incrementByAmount: (state, action) => {
            state.value += action.payload
        },
    },
})

// Action creators are generated for each case reducer function
export const { increment, decrement, incrementByAmount } = counterSlice.actions

export default counterSlice.reducer
// create a component in: features/counter/Counter.js
import React, { useState } from 'react'
import { useSelector, useDispatch } from 'react-redux'
import { decrement, increment, incrementByAmount } from './counterSlice'

export function Counter() {
    const count = useSelector(state => state.counter.value)
    const dispatch = useDispatch()
    const [amount, setAmount] = useState(0)

    return (
        <div>
            <div className="mb-8 space-x-4">
                <button
                    className="px-4 py-2 border border-black rounded hover:bg-green-300"
                    aria-label="Increment value"
                    onClick={() => dispatch(increment())}>
                    Increment
                </button>
                <span>{count}</span>
                <button
                    className="px-4 py-2 border border-black rounded hover:bg-green-300"
                    aria-label="Decrement value"
                    onClick={() => dispatch(decrement())}>
                    Decrement
                </button>
            </div>
            <div className="space-x-4">
                <input
                    type="text"
                    value={amount}
                    onChange={event => setAmount(event.target.value)}
                />
                <button
                    onClick={() =>
                        dispatch(incrementByAmount(parseInt(amount)))
                    }>
                    Increment By
                </button>
            </div>
        </div>
    )
}
// add to pages/dashboard.js
<Counter />