Flag of Ukraine
SymfonyCasts stands united with the people of Ukraine
This course is archived!
While the concepts of this course are still largely applicable, it's built using an older version of Symfony (4) and React (16).

JSX

Video not working?

It looks like your browser may not support the H264 codec. If you're using Linux, try a different browser or try installing the gstreamer0.10-ffmpeg gstreamer0.10-plugins-good packages.

Thanks! This saves us from needing to use Flash or encode videos in multiple formats. And that let's us get back to making more videos :). But as always, please feel free to message us.

This system of creating a "virtual DOM", or "tree" of React element objects and rendering that to the page is a really cool idea. But, it's already a total pain: imagine if we needed another React.createElement() inside of the span... then another element inside of that. Woof.

Because the React element objects are meant to represent HTML elements... it would be kinda cool if, instead, we could actually write HTML right here! Like, for example, what if we could say const el = then write an h2 tag with Lift Stuff! and add a span tag inside with a heart. I mean, that's exactly what we're ultimately building with React.createElement()!

... lines 1 - 3
const el = <h2>Lift Stuff! <span>❤️</span></h2>;
... lines 5 - 8

But, of course, this is not real JavaScript code: it's just me hacking HTML right into the middle of my JavaScript file. So, no surprise: PhpStorm is so angry with me. And, if you move back to the terminal tab that is running Webpack, oh, it's furious: Unexpected Token.

JSX & The Babel React Preset

Well... fun fact! This crazy HTML syntax is actually valid. Well, it's not official JavaScript: it's something called JSX - an extension to JavaScript. To use it, all we need to do is teach Babel how to parse it. Remember, Babel is the tool that reads our JavaScript and "transpiles" it, or "rewrites" it, into older JavaScript that all browsers can understand.

To teach it how to parse JSX, open your webpack.config.js file. In normal Webpack, you need to install and enable a React Babel preset: a rule that understands JSX. In Encore, you can do this by adding .enableReactPreset().

... lines 1 - 3
Encore
... lines 5 - 28
.enableReactPreset()
;
... lines 31 - 34

To make this take affect, go stop Encore and restart it:

yarn run encore dev --watch

Oh, it fails! Ah, we need to install a new package: copy the command name. Then, paste:

Tip

In newer versions of Encore, it will recommend that you install a more modern package - @babel/preset-react - which does the same thing.

yarn add @babel/preset-react@^7.0.0 --dev

By the way, the next version of this package will be called @babel/preset-react. So, if you see that package name in the future, don't worry, it's really the same thing.

And... done! Try Encore again:

yarn run encore dev --watch

Bah! It fails again - but this is my fault: I forgot to remove my extra el constant. After removing that, yea! Encore builds successfully! This means that it actually understands our crazy JSX code! Try it - move to your browser and refresh!

... lines 1 - 3
const el = <h2>Lift Stuff! <span>❤️</span></h2>;
console.log(el);
ReactDom.render(el, document.getElementById('lift-stuff-app'));

JSX Vs React.createElement()

We get the exact same output as before! An h2 with a span inside. Now, here's the really important part. Just like before, we're using console.log() to print this el. Check this out in the browser - woh! It's a React element object! It's the exact same thing we had before!

This special syntax - JSX - allows you to write, what looks like HTML right inside JavaScript. But in reality, Babel translates this into React.createElement() calls: this JSX generates the React.createElement() code we had before!

Hey, we solved our problem! We found a much prettier and more convenient way to use the React element system.

Making PhpStorm also Love JSX

Except... PhpStorm still hates me for using this. But, you can already see on top that it's asking us if we want to switch our language to support JSX. You can make the change there, or go to PhpStorm -> Preferences and search for "JSX". Under Languages & Frameworks, find JavaScript and change the language version to "React JSX".

Hit ok and... boom! PhpStorm is happy!

From now on, we will exclusively use JSX. But, don't forget what it really is! Just a fancy way of creating React element objects. Remembering this fact will help you understand React as things get more complex.

Adding the ESLint React Plugin

A few minutes ago, we installed & setup the eslint package. And now that we're using React, we can activate some new ESLint rules that will give us all kinds of cool notices and warnings that are specific to developing in React.

To install these new ESLint rules, move over to your terminal, find your open tab and run:

yarn add eslint-plugin-react --dev

Once that finishes, open the .eslintrc.js file. To use the rules from this package, update the extends option to have plugin:react/recommended.

You won't notice anything immediately, but as we keep developing in React, I'll point out the warnings that come from this.

Ok, we've learned how to create & render React element objects. But to really use React, we need to talk about React components.

Leave a comment!

11
Login or Register to join the conversation
Gustavo Avatar
Gustavo Avatar Gustavo | posted 3 years ago

Hi, i got this error in my browser console:

Module build failed (from ./node_modules/babel-loader/lib/index.js):

and i solved it adding this in my webpack.config.js:

.configureBabel(() => {}, {
useBuiltIns: 'usage',
corejs: 3
})

Thanks!

Reply

Hey Gustavo!

Thanks for the tip! I'm surprised you got an error specifically, but this logic IS now recommended in Encore (and you should get it by default when you install Encore these days).

Cheers!

Reply
Zacarías C. Avatar
Zacarías C. Avatar Zacarías C. | posted 3 years ago

Hello,

congratulations on the tutorial, it's great;)

I have this problem when extending ESLint with eslint-plugin-react, PHPStorm "says" that it cannot find the eslint-plugin-react module.

- the dependency exists and so it appears in package.json,
- webpack compiles cin showing no errors,
- ESLint is configured in PHPStorm with the automatic configuration option,
- the node interpreter is 12.10.0,
- the version of PHPStorm the 2019.2.3

Why is PHPStorm so angry with me?

Thanks in advance for any suggestions.

Reply
Zacarías C. Avatar

Solved! A bad ESLint PHPStorm configuration :)

1 Reply
Default user avatar
Default user avatar Roberto Briones Argüelles | posted 4 years ago

What do you use to get the balloon notifications in iTerm? :P

Reply

Hey Roberto Briones Argüelles!

That comes from Webpack Encore, which leverages webpack-notifier :). https://github.com/symfony/...

Fun, right?

Cheers!

Reply
Default user avatar
Default user avatar Imad Zairig | posted 5 years ago | edited

Hi,
i don't know why in my case i have always the same probleme, can't process jsx syntax in the section https://knpuniversity.com/screencast/reactjs/jsx#jsx-amp-the-babel-react-preset, i've installed all of that yarn add --dev react react-dom prop-types babel-preset-react and added .enableReactPreset() !!

the same error :


 2 | import ReactDom from 'react-dom';
> 3 | const el = <h2>Lift Stuff! <span>❤️</span></h2>;
    |            ^
Reply

Hey Imad Zairig !

Hmmm - yea, you're right - it looks like Babel still does not like your JSX syntax! Did you make sure to stop and restart Encore after adding .enableReactPreset()? If you did, then I'd love to see your full webpack.config.js file and know exactly what command you're using to run Encore :).

Cheers!

Reply
Default user avatar
Default user avatar Imad Zairig | weaverryan | posted 5 years ago | edited

Hi weaverryan ,

sorry, the probleme is caused by .babelrc file , once i delete it it works perfectly (y) ,

Thanks,

2 Reply
Default user avatar

Yes i did restart Encore, this is my webpack.config.js
var Encore = require('@symfony/webpack-encore');
const CopyWebpackPlugin = require('copy-webpack-plugin');
Encore
// the project directory where all compiled assets will be stored
.setOutputPath('public/build/')
// the public path used by the web server to access the previous directory
.setPublicPath('/build')
.createSharedEntry('layout', './assets/js/layout.js')
.addEntry('rep_log', './assets/js/rep_log.js')
.addEntry('rep_log_react', './assets/js/rep_log_react.js')
.addEntry('login', './assets/js/login.js')
.enableBuildNotifications()
// fixes modules that expect jQuery to be global
.autoProvidejQuery()
.addPlugin(new CopyWebpackPlugin([
// copies to {output}/static
{ from: './assets/static', to: 'static' }
]))
.enableSassLoader()
.enableSourceMaps(!Encore.isProduction())
.cleanupOutputBeforeBuild()
.enableVersioning(Encore.isProduction())
.enableReactPreset()
;
// export the final configuration
module.exports = Encore.getWebpackConfig();

and I run

yarn run encore dev --watch

Reply
Default user avatar
Default user avatar Imad Zairig | Imad Zairig | posted 5 years ago | edited

Hi Imad Zairig

i did work when i added "plugins": ["transform-react-jsx"] in .babelrc and without setPresetReact.

Reply
Cat in space

"Houston: no signs of life"
Start the conversation!

While the concepts of this course are still largely applicable, it's built using an older version of Symfony (4) and React (16).

What PHP libraries does this tutorial use?

// composer.json
{
    "require": {
        "php": "^7.2.0",
        "ext-iconv": "*",
        "composer/package-versions-deprecated": "^1.11", // 1.11.99
        "doctrine/doctrine-bundle": "^1.6", // 1.9.1
        "doctrine/doctrine-cache-bundle": "^1.2", // 1.3.3
        "doctrine/doctrine-fixtures-bundle": "~3.0", // 3.0.2
        "doctrine/doctrine-migrations-bundle": "^1.2", // v1.3.1
        "doctrine/orm": "^2.5", // v2.7.2
        "friendsofsymfony/jsrouting-bundle": "^2.2", // 2.2.0
        "friendsofsymfony/user-bundle": "dev-master#4125505ba6eba82ddf944378a3d636081c06da0c", // dev-master
        "sensio/framework-extra-bundle": "^5.1", // v5.2.0
        "symfony/asset": "^4.0", // v4.1.4
        "symfony/console": "^4.0", // v4.1.4
        "symfony/flex": "^1.0", // v1.17.6
        "symfony/form": "^4.0", // v4.1.4
        "symfony/framework-bundle": "^4.0", // v4.1.4
        "symfony/lts": "^4@dev", // dev-master
        "symfony/monolog-bundle": "^3.1", // v3.3.0
        "symfony/polyfill-apcu": "^1.0", // v1.9.0
        "symfony/serializer-pack": "^1.0", // v1.0.1
        "symfony/swiftmailer-bundle": "^3.1", // v3.2.3
        "symfony/twig-bundle": "^4.0", // v4.1.4
        "symfony/validator": "^4.0", // v4.1.4
        "symfony/yaml": "^4.0", // v4.1.4
        "twig/twig": "2.10.*" // v2.10.0
    },
    "require-dev": {
        "symfony/debug-pack": "^1.0", // v1.0.6
        "symfony/dotenv": "^4.0", // v4.1.4
        "symfony/maker-bundle": "^1.5", // v1.5.0
        "symfony/phpunit-bridge": "^4.0", // v4.1.4
        "symfony/web-server-bundle": "^4.0" // v4.1.4
    }
}

What JavaScript libraries does this tutorial use?

// package.json
{
    "dependencies": {
        "@babel/plugin-proposal-object-rest-spread": "^7.12.1" // 7.12.1
    },
    "devDependencies": {
        "@babel/preset-react": "^7.0.0", // 7.12.5
        "@symfony/webpack-encore": "^0.26.0", // 0.26.0
        "babel-plugin-transform-object-rest-spread": "^6.26.0", // 6.26.0
        "babel-plugin-transform-react-remove-prop-types": "^0.4.13", // 0.4.13
        "bootstrap": "3", // 3.3.7
        "copy-webpack-plugin": "^4.4.1", // 4.5.1
        "core-js": "2", // 1.2.7
        "eslint": "^4.19.1", // 4.19.1
        "eslint-plugin-react": "^7.8.2", // 7.8.2
        "font-awesome": "4", // 4.7.0
        "jquery": "^3.3.1", // 3.3.1
        "promise-polyfill": "^8.0.0", // 8.0.0
        "prop-types": "^15.6.1", // 15.6.1
        "react": "^16.3.2", // 16.4.0
        "react-dom": "^16.3.2", // 16.4.0
        "sass": "^1.29.0", // 1.29.0
        "sass-loader": "^7.0.0", // 7.3.1
        "sweetalert2": "^7.11.0", // 7.22.0
        "uuid": "^3.2.1", // 3.4.0
        "webpack-notifier": "^1.5.1", // 1.6.0
        "whatwg-fetch": "^2.0.4" // 2.0.4
    }
}
userVoice