mh71's avatar
Level 1

Laraval/React mix example doesn't display a page for me as illustrated on the tutorial.

https://code.tutsplus.com/tutorials/build-a-react-app-with-laravel-backend-part-2-react--cms-29443

The sample code in tutsplus link above works for me only if my welcome.blade.php is:

<!doctype html>
<html lang="{{ app()->getLocale() }}">
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Laravel React application</title>
        <link href="{{mix('css/app.css')}}" rel="stylesheet" type="text/css">
    </head>
    <body>
    <h2 style="text-align: center"> Laravel and React application </h2>
        <div id="root"></div>
        <script src="{{mix('js/app.js')}}" ></script>
    </body>
</html>

and my Main.js is

import React, { Component } from 'react';
import ReactDOM from 'react-dom';

/* An example React component */
class Main extends Component {
    render() {
        return (
            <div>
                <h3>All Products</h3>
            </div>
        );
    }
}

export default Main;

/* The if statement is required so as to Render the component on pages that have a div with an ID of "root";  
*/

if (document.getElementById('root')) {
    ReactDOM.render(<Main />, document.getElementById('root'));
}

...both as shown 2/5 of the way down on the tutsplus tutorial.

The problems for me begin if I go past those, into the Developing the React Application part of that tutorial. If I rewrite my Main.js file like it is there:

import React, { Component } from 'react';
import ReactDOM from 'react-dom';

/* Main Component */
class Main extends Component {

  constructor() {

    super();
    //Initialize the state in the constructor
    this.state = {
        products: [],
    }
  }
  /*componentDidMount() is a lifecycle method
   * that gets called after the component is rendered
   */
  componentDidMount() {
    /* fetch API in action */
    fetch('/api/products')
        .then(response => {
            return response.json();
        })
        .then(products => {
            //Fetched product is stored in the state
            this.setState({ products });
        });
  }

 renderProducts() {
    return this.state.products.map(product => {
        return (
            /* When using list you need to specify a key
             * attribute that is unique for each list item
            */
            <li key={product.id} >
                { product.title } 
            </li>      
        );
    })
  }

  render() {
   /* Some css code has been removed for brevity */
    return (
        <div>
              <ul>
                { this.renderProducts() }
              </ul> 
            </div> 
  
    );
  }
}

If I open that in a browser, I only see the "Laravel and React application" but no "All Products."

0 likes
14 replies
apex1's avatar

Did you get rid of this by mistake?

if (document.getElementById('root')) {
    ReactDOM.render(<Main />, document.getElementById('root'));
}
mh71's avatar
Level 1

Here is the C:\Users\Me\meblog\resources\js\components\Main.js (it's a Laravel 8 directory tree) that is in my test:

import React, { Component } from 'react';
import ReactDOM from 'react-dom';

/* Main Component */
class Main extends Component {

  constructor() {

    super();
    //Initialize the state in the constructor
    this.state = {
        products: [],
    }
  }
  /*componentDidMount() is a lifecycle method
   * that gets called after the component is rendered
   */
  componentDidMount() {
    /* fetch API in action */
    fetch('/api/products')
        .then(response => {
            return response.json();
        })
        .then(products => {
            //Fetched product is stored in the state
            this.setState({ products });
        });
  }

 renderProducts() {
    return this.state.products.map(product => {
        return (
            /* When using list you need to specify a key
             * attribute that is unique for each list item
            */
            <li key={product.id} >
                { product.title } 
            </li>      
        );
    })
  }

  render() {
   /* Some css code has been removed for brevity */
    return (
        <div>
              <ul>
                { this.renderProducts() }
              </ul> 
            </div> 
  
    );
  }
}

export default Main;

/* The if statement is required so as to Render the component on pages that have a div with an ID of "root";  
*/

if (document.getElementById('root')) {
    ReactDOM.render(<Main />, document.getElementById('root'));
}

It didn't have the last six lines in my prior failed tests, but adding them to the bottom now still yields only a "Laravel and React application" header at the top of the page with nothing else on it, no change.

My PostgreSQL table seeds and everything else is working except this.

But would the lack of data inside the table's created_at and updated_at fields cause the Products blockout to not appear at all on the left side of the page? Following the tutsplus instructions to the best of my knowledge, only the id, title, description, price, and availability columns are seeded.

apex1's avatar

Any errors in the console? Also check react dev tools, are the products loaded in your state ?

mh71's avatar
Level 1

No errors in the console. A nice blue Laravel Mix v6.0.11 rectangle and "Compiled Successfully in..." feedback accompanied by an audible chime, after yarn run dev.

"Also check react dev tools, are the products loaded in your state ?"

I'm not sure I'm doing this right; okay I've just typed "react dev tools" into the command line from inside my Laravel project's path and all I get is "'react' is not recognized as an internal or external command, operable program or batch file."

What does that mean? Because I've also got a create-react-app project going elsewhere on my machine. All I do to start that up is change my directory into it and then do npm start. My limited-knowledge takeaway from things thus far is React has to be separately loaded into any project I begin. Is that the case with React?

Then again, the import React and import ReactDOM lines at the top of the Main.js are not throwing any errors after I write yarn run dev.

apex1's avatar

Its a browser extension created by the react theme. If you're using chrome etc search for react dev tools and install it then open the dev console and click on the Components tab.

mh71's avatar
Level 1

I downloaded React DevTools and installed it onto Chrome as an extension. I see a Console tab, but nothing about Components anywhere. This is in the Console pane after I turn all the tree branches visible:

GET http://192.168.0.13:8000/api/products 500 (Internal Server Error)
componentDidMount @ app.js:1979
commitLifeCycles @ app.js:57412
commitLayoutEffects @ app.js:60401
callCallback @ app.js:37786
invokeGuardedCallbackDev @ app.js:37835
invokeGuardedCallback @ app.js:37890
commitRootImpl @ app.js:60139
unstable_runWithPriority @ app.js:66555
runWithPriority @ app.js:48637
commitRoot @ app.js:59979
finishSyncRender @ app.js:59405
performSyncWorkOnRoot @ app.js:59391
scheduleUpdateOnFiber @ app.js:58786
updateContainer @ app.js:61971
(anonymous) @ app.js:62356
unbatchedUpdates @ app.js:59501
legacyRenderSubtreeIntoContainer @ app.js:62355
render @ app.js:62438
./resources/js/components/Main.js @ app.js:2024
__webpack_require__ @ app.js:66816
./resources/js/app.js @ app.js:1845
__webpack_require__ @ app.js:66816
checkDeferredModulesImpl @ app.js:66954
__webpack_require__.x @ app.js:66967
(anonymous) @ app.js:66973
(anonymous) @ app.js:66974

Uncaught (in promise) SyntaxError: Unexpected token < in JSON at position 0
Promise.then (async)
componentDidMount @ app.js:1981
commitLifeCycles @ app.js:57412
commitLayoutEffects @ app.js:60401
callCallback @ app.js:37786
invokeGuardedCallbackDev @ app.js:37835
invokeGuardedCallback @ app.js:37890
commitRootImpl @ app.js:60139
unstable_runWithPriority @ app.js:66555
runWithPriority @ app.js:48637
commitRoot @ app.js:59979
finishSyncRender @ app.js:59405
performSyncWorkOnRoot @ app.js:59391
scheduleUpdateOnFiber @ app.js:58786
updateContainer @ app.js:61971
(anonymous) @ app.js:62356
unbatchedUpdates @ app.js:59501
legacyRenderSubtreeIntoContainer @ app.js:62355
render @ app.js:62438
./resources/js/components/Main.js @ app.js:2024
__webpack_require__ @ app.js:66816
./resources/js/app.js @ app.js:1845
__webpack_require__ @ app.js:66816
checkDeferredModulesImpl @ app.js:66954
__webpack_require__.x @ app.js:66967
(anonymous) @ app.js:66973
(anonymous) @ app.js:66974

DevTools failed to load SourceMap: Could not load content for http://192.168.0.13:8000/js/popper.js.map: 
HTTP error: status code 404, net::ERR_HTTP_RESPONSE_CODE_FAILURE

On http://192.168.0.13:8000/api/products the reported error is:

throw new BindingResolutionException("Target class [$concrete] does not exist.", 0, $e);

The other error, http://192.168.0.13:8000/, (.js index), is the

<!doctype html>

line at the top of the welcome.blade.php.

I deleted the doctype statement, recompiled the project, and nothing is different. I don't know what to do about the BindingResolutionException or if that's a problem.

apex1's avatar

Looks like something wrong with your Laravel code. Can you post the controller method for /api/products?

mh71's avatar
Level 1

I'm not seeing a path like that in Laravel 8. Nothing with a directory called api.

Would this be in the App\Http\Controllers namespace? I have a Products Controller class extending Controller:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Product;

class ProductsController extends Controller
{
    //

    public function index()
    {
        return Product::all();
    }

    public function show(Product $product)
    {
        return $product;
    }

    public function store(Request $request)
    {
        {
            $this->validate($request, [
            'title' => 'required|unique:products|max:255',
            'description' => 'required',
            'price' => 'integer',
            'availability' => 'boolean',
        ]);

//---me everything above this line inside function
        $product = Product::create($request->all());

        return response()->json($product, 201);
    }

    public function update(Request $request, Product $product)
    {
        $product->update($request->all());

        return response()->json($product, 200);
    }

    public function delete(Product $product)
    {
        $product->delete();

        return response()->json(null, 204);
    }
}

That's the whole of my ProductsController.php file. Those 7 lines including brackets content above the //--- line was added by myself into the existing store function; all the other stuff is preexisting. Insofar as the tutsplus narrative I'm attempting to follow.

apex1's avatar

You're using laravel 8, models now live in the Models directory. So on top of your file where you have use App\Product; change that to use App\Models\Product;

Could you also show your routes file (routes/api.php)?

mh71's avatar
Level 1

Here is the routes/api.php:

<?php

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;

/*
|--------------------------------------------------------------------------
| API Routes
|--------------------------------------------------------------------------
|
| Here is where you can register API routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| is assigned the "api" middleware group. Enjoy building your API!
|
*/
/*[me this here is the default API route that was here originally]:
Route::middleware('auth:api')->get('/user', function (Request $request) {
    return $request->user();
});
*/

/**
**Basic Routes for a RESTful service:
**Route::get($uri, $callback);
**Route::post($uri, $callback);
**Route::put($uri, $callback);
**Route::delete($uri, $callback);
**
*/


Route::get('products', 'ProductsController@index');

Route::get('products/{product}', 'ProductsController@show');

Route::post('products','ProductsController@store');

Route::put('products/{product}','ProductsController@update');

Route::delete('products/{product}', 'ProductsController@delete');

Attempting to follow https://code.tutsplus.com/tutorials/build-a-react-app-with-laravel-restful-backend-part-1-laravel-5-api--cms-29442 I commented out a few existing functional statement lines immediately underneath the the "API Routes" block of commentary.

apex1's avatar

Well thats a Laravel 5 tutorial and you're on Laravel 8. So some things are going to be different. Your routes should now be (Laravel 8)

use ...

Route::get('products', [ProductsController::class, 'index']);
Route::get('products/{product}', [ProductsController::class, 'show']);
etc...

And make sure to import the Product Controller.

use App\Http\Controllers\ProductsController;
mh71's avatar
Level 1

Thanks. After implementing the above, DevTools indicates there's now an error thrown by statement

 public function update(Request $request, Product $product)

in the ProductsController.php

mh71's avatar
Level 1

One red line error is:

Failed to load resource: the server responded with a status of 500 (Internal Server Error) :8000/api/products:1 

And the other one is:

192.168.0.13/:1 Uncaught (in promise) SyntaxError: Unexpected token < in JSON at position 0     192.168.0.13/:1

And then a yellow exclamation point warning below those two is:

DevTools failed to load SourceMap: Could not load content for http://192.168.0.13:8000/js/popper.js.map: HTTP error: status code 404, net::ERR_HTTP_RESPONSE_CODE_FAILURE

Please or to participate in this conversation.