gstreamer0.10-ffmpeg
gstreamer0.10-plugins-good
packages.
Time to install React! Find your open terminal: yarn add react
- and we also need a second package called react-dom
:
yarn add react react-dom --dev
react
is... um... React. react-dom
is the library we'll use to render our React app onto the page, the DOM. These are separate libraries because you can actually use React to render things in a non-browser environment.
Anyways, when that finishes, go back to rep_log_react.js
. Like with all libraries, to use React, we need to require or import it. I'll use the newer, far more hipster import
syntax in this tutorial to import React
from react
.
Here's the idea behind React: it's actually really beautiful: we create React element objects that represent HTML elements, like an h1 tag. These don't actually live on the page, they're just objects that describe HTML elements.
But then, we can tell React to look at our element objects, and use them to create real HTML elements on the page, or, on the DOM. This means that we will have a tree of element objects in React and a tree of element objects on the page. To say it a different way, we will have a virtual DOM in React and the real DOM on the page.
And... that's it! Of course, the magic is that, when we change some data on a React element object, React will update the corresponding DOM element automatically.
So... let's create some React elements! To really master this, yea... we're going to do things the hard way first. But, it will be totally worth it.
Create a new const el
set to React.createElement()
. Make this an h2
tag: we're building the title on top of the app. Pass null
for the second argument: but this is where you could pass an array of any HTML attributes for the element. These are called "props" in React - but more on that later. For the third argument, pass whatever you want to put inside, like text: "Lift History!".
import React from 'react'; | |
const el = React.createElement('h2', null, 'Lift History!'); | |
... lines 4 - 5 |
Cool! Let's console.log(el)
: I want you to see that this is just a simple object. Go refresh the page. The element is not, yet, being rendered to the screen in any way. It's just a React element that describes a potential HTML element.
... lines 1 - 3 | |
console.log(el); |
Now, go back to index.html.twig
. To render the element onto the page, we need a target. The existing app is rendered in this js-rep-log-table
element. Above this, add a new <div class="row">
and inside, an empty div we can render into with id=""
, how about, lift-stuff-app
. Then, for a bit more separation, add a bunch of line breaks and an <hr>
.
... lines 1 - 2 | |
{% block body %} | |
<div class="row"> | |
<div id="lift-stuff-app"></div> | |
</div> | |
<br><br><br><br><br><br> | |
<hr /> | |
... lines 11 - 55 | |
{% endblock %} | |
... lines 57 - 70 |
Awesome! Copy the id
of the div. To render React to the DOM, we need to use that other package we installed: import ReactDom
from react-dom
. Then, just, ReactDom.render()
to render our el
into document.getElementById('lift-stuff-app')
.
... line 1 | |
import ReactDom from 'react-dom'; | |
... lines 3 - 5 | |
ReactDom.render(el, document.getElementById('lift-stuff-app')); |
That's it! Step 1: create a React element object and, step 2, use ReactDom
and some boring, raw JavaScript to render it onto the page.
Let's go try it! Move over and refresh! Ha! We have our very first, but I, know very simple, React app. We deserve balloons!
Of course, in a real app, we're going to have more than just one element. Heck, we're going to have a big nested tree of elements inside of other elements, just like we do in normal HTML.
So... how could we put an element inside of our h2? First, break things onto multiple lines to keep our sanity. The answer is... by adding more and more arguments to the end of React.createElement()
. Each argument - starting with the third argument - becomes a new child that lives inside the h2
. For example, to create a nested span
element, use React.createElement()
with span
, null and a heart Emoji.
... lines 1 - 3 | |
const el = React.createElement( | |
'h2', | |
null, | |
'Lift History! ', | |
React.createElement('span', null, '❤️') | |
); | |
console.log(el); | |
... lines 12 - 13 |
Let's log el
again. Then, flip over and... refresh!
Ha! There it is! Inspect the element: yep, the h2 tag with a span inside. Check out the logged Element: it now has two "children", which is a React term: the text and another React element object.
Awesome! But... you've probably already noticed a problem. Building a real app with many nested elements is going to get really ugly... really quickly. This React "element" idea is great in theory.... but in practice, it's a nightmare! We need another tool to save us. That tool is love. I mean, JSX.
// 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
}
}
// 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
}
}