http://tinyurl.com/adn-react
Javascript
React JS
npm
document API
Javascript
React JS
npm
document API
ASK QUESTIONS !!!
js/jsx syntax, npm commands, API specs, etc.
Creating UI Elements
Rendering UI Elements
const App = () => (
<div>
<p>Hello, world</p>
</div>
)
ReactDOM.render(
<App />,
document.getElementById('root')
);HTML-like syntax that is transpiled into raw Javascript
const Box = ({ children }) => (
<div>
{children}
</div>
)
const App = () => (
<Box>
Hello, World!
</Box>
)JSX
const Box = ({ children }) => (
<div>
{children}
</div>
)
const App = () => (
<Box>
Hello, World!
</Box>
)JSX
var Box = function Box(_ref) {
var children = _ref.children;
return React.createElement("div", null, children);
};
var App = function App() {
return React.createElement(Box, null, "Hello, World!");
};Javascript
mkdir react && cd react
npm init
mkdir src/ && touch src/index.js(scripts available in talk repo README.md )
npm install --save-dev @babel/core
npm install --save-dev @babel/cli
npm install --save-dev @babel/plugin-transform-react-jsx(scripts available in talk repo README.md )
touch .babelrc(scripts available in talk repo README.md )
{
"plugins": [
[
"@babel/plugin-transform-react-jsx"
]
]
}Add the following to your .babelrc
(scripts available in talk repo README.md )
"scripts": {
"build": "babel src -d lib"
}Add the following build script to your package.json file
const Card = ({ title, text }) => (
<div>
<h2>{title}</h2>
{text}
</div>
);
const App = () => (
<div>
<Card title="Card One" text="this is card one!" />
</div>
);Add the following to components to your src/index.js file
npm run buildRun the build script:
{
"plugins": [
[
"@babel/plugin-transform-react-jsx",
{
"pragma": "createElement"
}
]
]
}Update .babelrc to remove the call to "React"
touch index.html
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8" />
<title>react</title>
</head>
<body></body>
<!-- USE OUR lib/index.js SCRIPT -->
<script type="text/javascript" src="lib/index.js"></script>
</html>Boilerplate for our index.html file
var Card = function Card(_ref) {
var title = _ref.title,
text = _ref.text;
return createElement(
"div",
null,
createElement("h2", null, title),
text
);
};
var App = function App() {
return createElement(
"div",
null,
createElement(
Card,
{
title: "Card One",
text: "this is card one!"
}
)
);
};
const createElement = (
nodeType, // String / Function
props, // Object
child1,
child2,
child3,
...,
childX
) => {
// TODO: create virtual DOM element
}A new virtual DOM node.
(An object that represents the contents of an HTML element)
<div>
<p>Hello, world</p>
</div>JSX
createElement("div",
null,
createElement("p",
null,
"Hello, world"))transpiles to...
which creates a virtual DOM node...
{
nodeName: "div",
props: null,
children: [
{
nodeName: "p",
props: null,
children: [
"Hello, world"
]
}
]
}
const createElement = (
nodeName, // String / Function
props, // Object / null
...children // any
) => {
return {
nodeName: nodeName,
props: props,
children: children
}
}
We're creating virtual DOM objects but aren't doing anything with them.
Need to render them to the real DOM
Look familiar?
ReactDOM.render(<App />, document.getElementById("root"))
Look familiar?
ReactDOM.render(<App />, document.getElementById("root"))
Let's rewrite our own version of ReactDOM.render
/** vnode { nodeName, props, children } **/
const render = vnode => {
// create DOM node from vnode
}
const render = vnode => {
// TODOS:
// create an element using the document object
// set attributes (props) of the newly created dom node
// render the children of vnode
// return the created dom element
}
const render = vnode => {
// TODOS:
// create an element using the document object
let node = document.createElement(vnode.nodeName)
// set attributes (props) of the newly created dom node
for (prop in vnode.props)
node.setAttribute(prop, vnode.props[prop])
// render the children of vnode
for(let i = 0; i < vnode.children.length; i++)
node.appendChild(render(vnode.children[i]))
// return the created dom element
return node
}
// JSX
<div>
Hello, world
</div>
// JS
createElement("div", null, "Hello, world");
// Virtual DOM (result from createElement)
{
nodeName: "div",
props: null,
children: ["Hello, world"]
}
// JSX
<Card title="Card!" text="Here is some text" />
// JS
createElement(Card, {
title: "Card!",
text: "Here is some text"
});
// Virtual DOM (result from createElement)
{
nodeName: Card,
props: {
title: "Card!",
text: "Here is some text"
},
children: []
}
const render = vnode => {
// TODOS:
// handle text nodes
// handle function components
// create an element using the document object
let node = document.createElement(vnode.nodeName)
// set attributes (props) of the newly created dom node
for (prop in vnode.props)
node.setAttribute(prop, vnode.props[prop])
// render the children of vnode
for(let i = 0; i < vnode.children.length; i++)
node.appendChild(render(vnode.children[i]))
// return the created dom element
return node
}
const render = vnode => {
// TODOS:
// handle text nodes
if(typeof vnode === "string")
return document.createTextNode(vnode)
// handle function components
if(typeof vnode.nodeName === "function")
return render(vnode.nodeName({
...vnode.props,
children: vnode.children
}))
let node = document.createElement(vnode.nodeName)
for (prop in vnode.props)
node.setAttribute(prop, vnode.props[prop])
for(let i = 0; i < vnode.children.length; i++)
node.appendChild(render(vnode.children[i]))
return node
}
const Card = ({ title, text }) => (
<div>
<h2>{title}</h2>
<p>{text}</p>
</div>
)
const App = () => (
<div>
<Card title="Card One" text="this is card one!" />
</div>
)
// render app to the document body
document.body.appendChild(render(<App />))
const Card = ({ children }) => (
<div>
{children}
</div>
)
const App = () => (
<Card>
Hello, world
</Card>
)
createElement("div", null, ["Hello, world"])
{
nodeName: "div",
props: null,
children: [["Hello, world"]] // <-- the issue
}When attempting to render our Card component we generate the following
...which returns the following virtual DOM
Bottom line: When rendering children, we will attempt to call render on a nested array
const createElement = (
nodeName, // String / Function
props, // Object / null
...children // any
) => {
return {
nodeName,
props,
children: children.flat() // <-- the fix
}
}
Application state management is a big part of what the React library provides
1.) Access to our global state
2.) Ability to set the global state
3.) Upon updating the state, initiate a page re-render
Our Requirements:
Class component support
Efficient Rendering / Diffing
Alternative state management techniques
Component life-cycle methods
Event System
PropType System
Fragments
....
A LOT.