'How can I create and use 404.vue in Inertiajs2 app?

How with laravel, Inertiajs2, vuejs3 can I catch invalid url ? If I create file

resources/views/errors/404.blade.php

is it triggered, but I dislike using blade file in this case...

Additive information :

I modified file app/Exceptions/Handler.php

class Handler extends ExceptionHandler {

...
public function render($request, Throwable $e)
{
    $response = parent::render($request, $e);

    // I commented environment checking for development
    if ( /*!app()->environment(['local', 'testing']) &&*/ in_array($response->status(), [500, 503, 404, 403])) {

        // As I want to show separate file for any error I try 404
        return Inertia::render('404', ['status' => $response->status()])
                      ->toResponse($request)
                      ->setStatusCode($response->status());
    } else if ($response->status() === 419) {
        return back()->with([
            'message' => 'The page expired, please try again.',
        ]);
    }

    return $response;
}

I created a file resources/js/Pages/404.vue with lines :

<template>

    <frontend-layout>

        resources/js/Pages/404.vue

    </frontend-layout>


</template>

<script>
import FrontendLayout from '@/Layouts/FrontendLayout'

import {ref, computed, onMounted} from 'vue'
import { defineComponent } from 'vue'

export default defineComponent({
    name: '404Page',
    components: {
        FrontendLayout,
    },
    setup() {
        function HomeOnMounted() {
        } // function HomeOnMounted() {

        onMounted(HomeOnMounted)

        return { // setup return
            // Page state
        }
    }, // setup() {

})
</script>

and I got error :

[2022-05-18 09:52:14] local.ERROR: Uncaught InvalidArgumentException: View [app] not found. in /ProjectPath/vendor/laravel/framework/src/Illuminate/View/FileViewFinder.php:137
Stack trace:
    #0 /ProjectPath/vendor/laravel/framework/src/Illuminate/View/FileViewFinder.php(79): Illuminate\View\FileViewFinder->findInPaths()
#1 /ProjectPath/vendor/laravel/framework/src/Illuminate/View/Factory.php(137): Illuminate\View\FileViewFinder->find()
#2 /ProjectPath/vendor/laravel/framework/src/Illuminate/Routing/ResponseFactory.php(87): Illuminate\View\Factory->make()
#3 /ProjectPath/vendor/laravel/framework/src/Illuminate/Support/Facades/Facade.php(337): Illuminate\Routing\ResponseFactory->view()
#4 /ProjectPath/vendor/inertiajs/inertia-laravel/src/Response.php(113): Illuminate\Support\Facades\Facade::__callStatic()
#5 /ProjectPath/app/Exceptions/Handler.php(52): Inertia\Response->toResponse()
#6 /ProjectPath/vendor/laravel/framework/src/Illuminate/Foundation/Bootstrap/HandleExceptions.php(220): App\Exceptions\Handler->render()
#7 /ProjectPath/vendor/laravel/framework/src/Illuminate/Foundation/Bootstrap/HandleExceptions.php(197): Illuminate\Foundation\Bootstrap\HandleExceptions->renderHttpResponse()
#8 /ProjectPath/vendor/laravel/framework/src/Illuminate/Foundation/Bootstrap/HandleExceptions.php(255): Illuminate\Foundation\Bootstrap\HandleExceptions->handleException()
#9 [internal function]: Illuminate\Foundation\Bootstrap\HandleExceptions->Illuminate\Foundation\Bootstrap\{closure}()
#10 {main}
thrown {"exception":"[object] (Symfony\\Component\\ErrorHandler\\Error\\FatalError(code: 0): Uncaught InvalidArgumentException: View [app] not found. in /ProjectPath/vendor/laravel/framework/src/Illuminate/View/FileViewFinder.php:137
    Stack trace:
        #0 /ProjectPath/vendor/laravel/framework/src/Illuminate/View/FileViewFinder.php(79): Illuminate\\View\\FileViewFinder->findInPaths()
    #1 /ProjectPath/vendor/laravel/framework/src/Illuminate/View/Factory.php(137): Illuminate\\View\\FileViewFinder->find()
    #2 /ProjectPath/vendor/laravel/framework/src/Illuminate/Routing/ResponseFactory.php(87): Illuminate\\View\\Factory->make()
    #3 /ProjectPath/vendor/laravel/framework/src/Illuminate/Support/Facades/Facade.php(337): Illuminate\\Routing\\ResponseFactory->view()
    #4 /ProjectPath/vendor/inertiajs/inertia-laravel/src/Response.php(113): Illuminate\\Support\\Facades\\Facade::__callStatic()
    #5 /ProjectPath/app/Exceptions/Handler.php(52): Inertia\\Response->toResponse()
    #6 /ProjectPath/vendor/laravel/framework/src/Illuminate/Foundation/Bootstrap/HandleExceptions.php(220): App\\Exceptions\\Handler->render()
    #7 /ProjectPath/vendor/laravel/framework/src/Illuminate/Foundation/Bootstrap/HandleExceptions.php(197): Illuminate\\Foundation\\Bootstrap\\HandleExceptions->renderHttpResponse()
    #8 /ProjectPath/vendor/laravel/framework/src/Illuminate/Foundation/Bootstrap/HandleExceptions.php(255): Illuminate\\Foundation\\Bootstrap\\HandleExceptions->handleException()
    #9 [internal function]: Illuminate\\Foundation\\Bootstrap\\HandleExceptions->Illuminate\\Foundation\\Bootstrap\\{closure}()
    #10 {main}
    thrown at /ProjectPath/vendor/laravel/framework/src/Illuminate/View/FileViewFinder.php:137)
[stacktrace]
#0 /ProjectPath/vendor/laravel/framework/src/Illuminate/Foundation/Bootstrap/HandleExceptions.php(244): Symfony\\Component\\ErrorHandler\\Error\\FatalError->__construct(message: '...', code: '...', error: '...', traceOffset: '...', traceArgs: '...', trace: '...')
#1 /ProjectPath/vendor/laravel/framework/src/Illuminate/Foundation/Bootstrap/HandleExceptions.php(231): Illuminate\\Foundation\\Bootstrap\\HandleExceptions->fatalErrorFromPhpError(error: '...', traceOffset: '...')
#2 /ProjectPath/vendor/laravel/framework/src/Illuminate/Foundation/Bootstrap/HandleExceptions.php(255): Illuminate\\Foundation\\Bootstrap\\HandleExceptions->handleShutdown()
#3 /ProjectPath/vendor/laravel/framework/src/Illuminate/Foundation/Bootstrap/HandleExceptions.php(0): Illuminate\\Foundation\\Bootstrap\\HandleExceptions->Illuminate\\Foundation\\Bootstrap\\{closure:/ProjectPath/vendor/laravel/framework/src/Illuminate/Foundation/Bootstrap/HandleExceptions.php:254-256}()
#4 {main}
"} 


as I have 3 layouts (without default app) I have 3 files :
resources/views/layouts/adminlte.blade.php
resources/views/layouts/frontend.blade.php
resources/views/layouts/user.blade.php

and in app/Http/Middleware/HandleInertiaRequests.php I have :

public function rootView(Request $request)
{

    if ($request->segment(1) == 'user') {
        return 'layouts/user';
    }
    if ($request->segment(1) == 'admin') {
        return 'layouts/adminlte'; 
    }

    return 'layouts/frontend'; 
}

I added one more file : /resources/views/layouts/app.blade.php

But I still got error :

 View [app] not found

Looks like all defaults error codes demands standard /resources/views/layouts/app.blade.php file, but why I still got error after I added this file ?

Thanks in advance!



Solution 1:[1]

Error handling is described in the Inertia.js docs.

You need to extend the render() method in your App\Exceptions\Handler.php so it will send a Inertia response back to the client when it hits an error.

It's important to return an Inertia response only in certain scenarios, because doing this will prevent the default Laravel error handling from running and you won't get the useful debug info during development. The code bellow only returns an Inertia response in production.

use Throwable;
use Inertia\Inertia;

/**
 * Prepare exception for rendering.
 *
 * @param  \Throwable  $e
 * @return \Throwable
 */
public function render($request, Throwable $e)
{
    $response = parent::render($request, $e);

    if (!app()->environment(['local', 'testing']) {
        return Inertia::render('Error', ['status' => $response->status()])
            ->toResponse($request)
            ->setStatusCode($response->status());
    }

    return $response;
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Matheus Dal'Pizzol