0

I'm building an application with Laravel + React. I use Inertia.js to combine the two. The project was generated through Vite.js, which is also used.

I now have built a table, which is responsive so I can make changes to it and these changes should be saved to the database when I click save. This works, however, I keep getting the error this.resolveComponent is not a function whenever the table should be re-rendered. It seems that I cannot re-render components for some reason and I tried everything I can think of.

app.jsx

import './bootstrap';
import '../css/app.css';

import { createRoot } from 'react-dom/client';
import { createInertiaApp } from '@inertiajs/react';
import { resolvePageComponent } from 'laravel-vite-plugin/inertia-helpers';

const appName = import.meta.env.VITE_APP_NAME || 'Laravel';
createInertiaApp({
    title: (title) => `${title} - ${appName}`,
    resolve: (name) => resolvePageComponent(`./Pages/${name}.jsx`, import.meta.glob('./Pages/**/*.jsx')),
    setup({ el, App, props }) {
        const root = createRoot(el);

        root.render(<App {...props} />);
    },
    progress: {
        color: '#4B5563',
    },
});

Can you guys give me any advice? I cannot seem to fix this and there is not much online about this issue either.

2 Answers 2

0

Alright, I don't know what I did wrong, but I decided to create a clean Laravel/React/InertiaJS (+ Laravel Breeze for the auth stuff) stack using Vite and then moved all my code over to the new project. I suppose something was wrong with my project, as of now it works perfectly.

If anyone ever wants to try the same solution, here are the commands I used to build a new project (these instructions were generated using ChatGPT):

  1. Install Laravel: Ensure you have Composer installed, then create a new Laravel project.
    composer create-project --prefer-dist laravel/laravel myshop
    cd myshop
    

2. Install Laravel Breeze

  1. Install Laravel Breeze: Laravel Breeze provides a minimal implementation of all of Laravel's authentication features using Blade. Since we want to use React with InertiaJS, we need the React preset.

    composer require laravel/breeze --dev
    php artisan breeze:install react
    
  2. Install & Build Frontend Assets:

    npm install && npm run dev
    

3. Install Laravel InertiaJS

  1. Install InertiaJS Server-side:

    composer require inertiajs/inertia-laravel
    
  2. Install Inertia Middleware:

    After installation, register the middleware in your App\Http\Kernel.php file:

    'web' => [
        // Other middleware...
        \App\Http\Middleware\HandleInertiaRequests::class,
    ],
    

4. Setup Vite with React and InertiaJS

  1. Install Client-side Dependencies with Vite:

    npm install @inertiajs/react @vitejs/plugin-react vite axios
    
  2. Configure Vite: Replace contents of your vite.config.js with:

    import { defineConfig } from 'vite';
    import react from '@vitejs/plugin-react';
    import path from 'path';
    
    export default defineConfig({
        plugins: [react()],
        resolve: {
            alias: {
                '@': path.resolve(__dirname, 'resources/js'),
            },
        },
        server: {
            watch: {
                usePolling: true,
            },
        },
    });
    

5. Setup Inertia React Components

  1. Update Resources JS Structure: Create folders for your React components if they don't already exist:

    mkdir -p resources/js/Pages resources/js/Components
    touch resources/js/Pages/Dashboard.jsx resources/js/Pages/Login.jsx
    
  2. Create an app.jsx entry point: In resources/js, create app.jsx:

    import React from 'react';
    import { render } from 'react-dom';
    import { createInertiaApp } from '@inertiajs/react';
    import { InertiaProgress } from '@inertiajs/progress';
    import { resolvePageComponent } from 'laravel-vite-plugin/inertia-helpers';
    
    createInertiaApp({
        resolve: (name) => resolvePageComponent(
            `./Pages/${name}.jsx`,
            import.meta.glob('./Pages/**/*.jsx')
        ),
        setup({ el, App, props }) {
            render(<App {...props} />, el);
        },
    });
    
    InertiaProgress.init();
    

6. Update Laravel Blade View

  1. Add Main Inertia View: Update resources/views/app.blade.php or create it:
    <!DOCTYPE html>
    <html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
        <head>
            <meta charset="utf-8">
            <meta name="viewport" content="width=device-width, initial-scale=1">
            <title inertia>{{ config('app.name', 'Laravel') }}</title>
            @viteReactRefresh
            @vite('resources/js/app.jsx')
            @inertiaHead
        </head>
        <body class="font-sans antialiased">
            @inertia
        </body>
    </html>
    

7. Run Migrations and Build Project

  1. Run Migrations:

    php artisan migrate
    
  2. Run the Development Server:

    php artisan serve
    npm run dev
    

8. Setup Inertia Links in Laravel Breeze

  1. Update Auth Components: Ensure that your Breeze auth components use Inertia for navigation. You can wrap form submissions in a useForm hook from Inertia, for instance. For example, in your Login.jsx:
    import React from 'react';
    import { useForm } from '@inertiajs/react';
    
    export default function Login() {
        const { data, setData, post } = useForm({
            email: '',
            password: '',
            remember: false,
        });
    
        const submit = (e) => {
            e.preventDefault();
            post(route('login'));
        };
    
        return (
            <form onSubmit={submit}>
                {/* Your form fields */}
            </form>
        );
    }
    
    
Sign up to request clarification or add additional context in comments.

Comments

0

I encountered a similar issue where invoking Inertia.reload() within the onSuccess callback resulted in the error:

this.resolveComponent is not a function

Problem:

Calling Inertia.reload() inside the onSuccess callback can cause this error because the Inertia instance may not have the necessary context to resolve components during that callback execution.

Solution:

Instead of manually calling Inertia.reload(), you can achieve the desired behavior by utilizing the only and preserveState options directly within the post method. This approach ensures that only the specified data is reloaded, and the component state is preserved without triggering the aforementioned error.

Example:

from this:

post(route("users.store"), {
    onSuccess: (response) => {
        Inertia.reload({ only: ['users'] });
        
        // Handle success (if needed)
    },
    onError: (errors) => {
        // Handle errors
    }
});

to this:

post(route("users.store"), {
    only: ['users'],         // Reload only the 'users' data
    preserveState: true,     // Preserve the current component state
    onSuccess: (response) => {
        // Handle success (if needed)
    },
    onError: (errors) => {
        // Handle errors
    }
});

Explanation:

  • only: ['users']: This option tells Inertia to reload only the users data from the server, avoiding a full page reload.

  • preserveState: true: Ensures that the current component state is maintained across the reload, preventing loss of local state or form data.

By structuring your post request this way, you eliminate the need to call Inertia.reload() manually, thereby avoiding the context issue that leads to the this.resolveComponent is not a function error.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.