By default, the newest versions of Laravel ship with scaffolding for the JavaScript framework Vue.js. This is great for getting started quickly... if you plan on using it.

Another popular choice for front-end JavaScript is Facebook's React. Previously in Laravel, if you wanted to use React in your project you had to manually remove Vue and add React. While it wasn't terribly difficult, it did require pulling in the packages, adding it to your app.js or bootstrap.js files, fixing your webpack files, and so on.

But now that Laravel 5.5 has shipped, there is a new artisan command available that handles all of this for us.

php artisan preset react

This short command replaces all the Vue scaffolding with React. If you would like to follow along with the rest of this lesson, open your terminal and go to wherever you place your Laravel projects.

laravel new laravel-react
cd laravel-react
php artisan preset react
npm install

If you'd prefer to just look at the finished project, I have it hosted over on GitHub.

Now that you have a fresh Laravel installation with React scaffolding in place, you're ready to go! Using React within another project such as this can be a little confusing, so we'll build a simple counter component to get started.

When you first run the preset command, you will be given a default React component located at /resources/assets/js/components/Example.js. Rename this to Counter.js, and strip out all the example fluff and we're left with this much simpler component.

import React, { Component } from 'react';
import ReactDOM from 'react-dom';
 
export default class Counter extends Component {
    render() {
        return (
            <div classname="container">
                <p>Counter Component</p>
            </div>
        );
    }
}
if (document.getElementById('counter')) {
    ReactDOM.render(<counter></counter>, document.getElementById('counter'));
}

All we did was rename the component and take out the extraneous code. Since we renamed the component file, we also have to go into our /resources/assets/js/app.js file and update the name there as well So now instead of requiring the Example component, we require our Counter component.

require('./components/Counter');

Finally, to get the component displaying on the screen so we know everything is working as expected, we can edit the welcome.blade.php view to display our component. Simply remove the default <body> and replace it with this bit of HTML.

<body>
    <div class="container">
        <div id="counter"></div>
    </div>
    <script src="/js/app.js"></script>
</body>

Because we used `ReactDOM.render(..., document.getElementById('counter'));` in our component, it will find that `<div id="counter"></div>` and turn it into our new Counter component. The script is simply our main app.js script that everything gets compiled down into when you run the build script. Speaking of which, make sure to run that now that we've created our component.

npm run dev

Now if you visit your project in your browser, you should see an extremely exciting "Counter Component" paragraph on the page.

Don't worry, it gets better. If you want to catch up with the GitHub project, you can jump to the Install and Run Dev commit.

Now that our component is displaying on the page, it means we can start adding some custom functionality. Since we said this was going to be a counter, let's follow through on that promise.

The first thing we'll do is setup the state for the counter, which is where the current count will be stored. Go back into your Counter.js file and add this constructor just inside the component declaration.

constructor() {
    super();
    this.state = {
        count: 0
    };
}

Since we have the state declared, we may as well start displaying it on the page. Change the render function to output our exciting new count state instead of that boring old paragraph.

render() {
    return (
        <div classname="container">
            <p>{ this.state.count }</p>
        </div>
    );
}

Run your build script again to compile all of this down, and reload your page to see the current count get output to the screen! If you've fallen behind or simply want to see the code, we just completed the Setup State commit.

It's still not very much like a counter though, since we can't actually interact with it to change the state. To make this as generic as possible so it can count whatever types of things you want, we'll simply add two buttons: one to increase the count and one to decrease it. Put these right below where we output the count.

<button onclick="{this.increment}">+</button>
<button onclick="{this.decrement}">-</button>

These buttons would work great, but right now we don't have an increment or a decrement function, so let's add those next. Put these two functions right between the constructor and the render function.

increment() {
    let count = this.state.count;
    count++;
    this.setState({count: count});
}
decrement() {
    let count = this.state.count;
    count--;
    this.setState({count: count});
}

They're pretty straightforward. Running the increment function will increase the count state by one, running the decrement function will decrease the count state by one. Since we are using `this` inside of a function on a component though, don't forget to bind `this` to the function. To learn more about why you need to do this and other ways to do so, check out these 6 Ways to Bind JavaScript's this keyword in React.

Personally, I bind the functions at the end of my component's constructor like so.

constructor() {
    [...]
    this.increment = this.increment.bind(this);
    this.decrement = this.decrement.bind(this);
}

Now you can successfully compile your code one more time and have a fully functioning React component inside Laravel! If you check out the site in your browser, you should see the default count of 0 and two little buttons. Clicking on either one should change the count and update the value being displayed just like you would expect.

There you have it! Now you can quickly and easily get started using React in all of your Laravel projects (if you want) without having to fumble around in configuration files.

You can check out the full source code of this example over on GitHub.