Limenius / ReactBundle

Client and Server-side React.js rendering in a Symfony Bundle
MIT License
390 stars 53 forks source link

Cannot render on the server side #27

Closed LoicGoyet closed 6 years ago

LoicGoyet commented 6 years ago

Hello, I am currently doing some POC with the bundle for future developments. My react my is really simple :

// main.js
import React from 'react'
import ReactOnRails from 'react-on-rails'
import DemoApp from './react/demoApp'

const DemoApp = ({foo, ...props}) => (
    <h1>Hello world ! A react app ! {foo}</h1>
)

ReactOnRails.register({ DemoApp })

and my symfony view is quite simple too

{{ react_component('DemoApp', {
    "props": {
        "foo": "bar"
    }
}) }}

<!-- main.js file built up by Encore -->
<script src="{{ asset('build/main.js') }}"></script>

This works great when the default_rendering param is set as 'client_side', but when I switch it to 'client_side' or 'both' it throws the following exception :

An exception has been thrown during the rendering of a template ("PhpExecJs: Cannot autodetect any JavaScript runtime").

For now none of the past issue reported solved my problem.

I tried to install your Symfony React Sandbox Project on my machine, and I wasn't able to fetch vendors through composer because of my version of PHP : I am with PHP 7.0 and the vendors requires 7.1 to be installed.

Maybe your bundle require PHP version to be 7.1 ? (the project I am working on require 7.0 :( )

Thanks ;)

grimpows commented 6 years ago

for server side rendering, you should have nodeJs installed or have V8js extension enabled for php ^^ but i dont understand how you could build/run your main.js without have node installed .... can you use the command "node -v" on a terminal ?

LoicGoyet commented 6 years ago

@grimpows node is installed on my env. When I do node -v it returns 'v8.9.1'.

By the way, I finally succeed to install the React Sandbox Project, and it works fine on my computer, whatever the rendering is.

This would mean that the issue is on my project config I guess, but I have no clue :(

I also figure out that if the rendering is set via the twig extension {{ react_component() }}, as

{{ react_component('DemoApp', {
    "rendering": 'both',
    "props": {
        "foo": "bar"
    }
}) }}

and my default_rendering param as "client_side" my error is not the same, i get 'Call to a member function render() on null'

grimpows commented 6 years ago

looke like your react code is the prob, try returning code in main.js like this

import React from 'react'
import ReactOnRails from 'react-on-rails'
import DemoApp from './react/demoApp'

const DemoApp = ({foo, ...props}) => {
    return (   <h1>Hello world ! A react app ! {foo}</h1> )
}

ReactOnRails.register({ DemoApp })

note that as you rewrite DemoApp, i dont see the interest of import it, you can also remove the import DemoApp

LoicGoyet commented 6 years ago

Yeah about the import, this is just an oversight for my issue's snippet. On my code, the <DemoApp/> component definition is in a different javascript file that I import into my main.js file. In order to simplify my snippet in this issue, I gathered all the code into one chunk but forgot to remove the import line.

I changed my component as you suggested, but it doesn't change anything as I expected. The way I wrote it initially is just a shorthand to your version. I define my stateless component with an arrow function, and so I can directly return my expression (here my jsx template) without creating any scope.

This is totally valid es6 code, and if it wasn't the component would not be rendered in 'client_side' mode.

grimpows commented 6 years ago

if the react sandbox work for you, maybe you can import step by step your react code in it and see what cause the serverside problem ...

georgiana-gligor commented 6 years ago

@LoicGoyet did you solve this in the end? I seem to be encountering the error myself and have been unsuccessful so far to fixx it.

LoicGoyet commented 6 years ago

@georgiana-gligor well I solved it with the help of the symfony-react-sandbox repo, but actually I didn't really find out what the issue was on the first place. Today I use the server rendering with the external server method rendering components with a node server, which is more suited for production.

Maybe give some code sample, I could look at it a bit

georgiana-gligor commented 6 years ago

I did my fair share of debugging and will leave the solution that worked for me here, in hope it will help someone else. In my case, the misbehaviour of the server_side rendering was due to the fact that PhpExecJs didn't have any $PATH to work with (it was null). So setting it as an environment variable inside the nginx configuration file did the trick.