DEV Community

Zubair Mohsin
Zubair Mohsin

Posted on

Laravel and Inertia with React and TypeScript

  • Create a fresh Laravel project.
laravel new inertia-typescript
Enter fullscreen mode Exit fullscreen mode

Back-End

  • Let's setup back-end for Inertia.js by following instructions from here.
composer require inertiajs/inertia-laravel
Enter fullscreen mode Exit fullscreen mode
  • Create Root template at resources/views/app.blade.php with following contents:
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" />
    <link href="{{ mix('/css/app.css') }}" rel="stylesheet" />
    <script src="{{ mix('/js/app.js') }}" defer></script>
  </head>
  <body>
    @inertia
  </body>
</html>
Enter fullscreen mode Exit fullscreen mode
  • Create a route in routes/web.php
use Inertia\Inertia;

Route::get('home', function(){
  return Inertia::render('Home');
});
Enter fullscreen mode Exit fullscreen mode

Note: We haven't yet created Home component specified inside render method.

Front-End

Let's set up our front-end by following instructions from here.

  • We'll start with bunch of installations:
npm install react react-dom @types/react
Enter fullscreen mode Exit fullscreen mode
npm install @inertiajs/inertia @inertiajs/inertia-react
Enter fullscreen mode Exit fullscreen mode
npm install --save-dev ts-loader typescript
Enter fullscreen mode Exit fullscreen mode
  • Initialize typescript by creating tsconfig.json file using below command:
tsc --init --jsx react
Enter fullscreen mode Exit fullscreen mode
  • Initialize our Inertia app like below inside resources/js/app.js:
import { InertiaApp } from '@inertiajs/inertia-react'
import React from 'react'
import { render } from 'react-dom'

const app = document.getElementById('app')

render(
  <InertiaApp
    initialPage={JSON.parse(app.dataset.page)}
    resolveComponent={name => import(`./Pages/${name}`).then(module => module.default)}
  />,
  app
)
Enter fullscreen mode Exit fullscreen mode
  • Create our Home component at resources/js/Pages/Home.tsx
import React from "react";

const Home = () => {
    let foo: string = "React";
    const bar: string = "TypeScript";

    return (
        <h1>
            Hello {foo} + {bar}
        </h1>
    );
};

export default Home;
Enter fullscreen mode Exit fullscreen mode

Notice that I have .tsx extension instead of .jsx

  • Change mix.js to mix.ts in webpack.mix.js file:
mix.ts('resources/js/app.js', 'public/js')
    .postCss('resources/css/app.css', 'public/css', [
        //
    ]);
Enter fullscreen mode Exit fullscreen mode
  • Next, npm run dev

  • Read Update below ๐Ÿ‘‡๐Ÿผ

๐Ÿ”ด You will face an error here inside your resources/js/app.js file because we have written some JSX syntax to initialize our app but we haven't installed react-preset so that Babel can understand it.

  • Lets install @babel/preset-react as dev dependency.
npm install --save-dev @babel/preset-react
Enter fullscreen mode Exit fullscreen mode
  • Create a .babelrc file at root of our project with following contents:
{
  "presets": ["@babel/preset-react"]
}
Enter fullscreen mode Exit fullscreen mode
  • Run npm run dev again and you should be able to compile your assets now. Visit the /home route to verify that you are able to see the output in browser.

Disclaimer: This is not the definitive guide on setting up TypeScript with React for Laravel and Inertia. This is just how I am proceeding with this setup.

If you find any mistakes, or know a better approach please leave your feedback in comments below ๐Ÿ™๐Ÿผ

Demo source code can be found here.

Update

Amitav Roy mentioned on Twitter if we can completely ditch JavaScript and also be able to avoid @babel/preset-react step above. Turns out it can be done easily.
Commit from Demo repository that shows how it can be done: 49be431

Top comments (7)

Collapse
 
hasnatbabur profile image
Hasnat Babur

Nice one. Thanks

Collapse
 
andyyou profile image
andyyou

I found that code split feature is not working after setup. Originally pages will divide to different js after building but now all in app.js

Collapse
 
andyyou profile image
andyyou

I solve the problem. If you want to use Inertia.js with code split (dynamic imports) you should setup tsconfig.json

{
  "module": "esnext",
  "moduleResolution": "node", 
}
Enter fullscreen mode Exit fullscreen mode

Ref here: stackoverflow.com/questions/563757...

Collapse
 
ddnazzah profile image
Dieu-Donne Nazzah

Nice, Thanks. The only suggestion to add is since every thing is being bundled, all dependencies can actually be devDepencies

Collapse
 
risurina profile image
Ronnie Isurina

Nice, Thanks!

Collapse
 
sreek86 profile image
Sreekant Krishnan

I'm getting 404 error. I know it has something to do with Laravel being on a sub-directory, but not able to figure out how to get a workaround. Can you please help?

Collapse
 
friday_joshua profile image
Friday Joshua

Thanks so much. I've been on this all night and finally got it right.
I kind of mixed up the dependencies, my project is setup with vite but your example uses webpack.