Skip to content

Instantly share code, notes, and snippets.

@bbrt3
Last active June 20, 2022 08:22
Show Gist options
  • Save bbrt3/ccc8d66148091468d20fea503e8a8235 to your computer and use it in GitHub Desktop.
Save bbrt3/ccc8d66148091468d20fea503e8a8235 to your computer and use it in GitHub Desktop.
React
/*
React's basic components:
a) components - they are like functions, we invoke function with some input and they give us some output,
- input: props, output: UI
- reusable and composable
- <Component />
- can manage a private state
b) reactive updates
- react will react
- take updates to the browser
c) virtual views in memory
- generate html using JS
- no html template language
- tree reconcililation
React components
a) Function components
- simpler, preferred
b) Class components
- more powerful
*/
// props
// immutable
const MyComponent = (props) => {
return (
<domElementOrComponent />
);
}
// state
// mutable
const MyComponent extends React.Component {
return (
<domElementOrComponent />
);
}
// JSX is what gets generated from props + state
class Hello extends React.Component {
render() {
return (
// here we just use HTML, but what react does it translates it to AAA first then to actual browser content
// this is JSX, that later gets compiled to browser-friendly code (react api calls)
<div className="container">
<h1>Getting started</h1>
</div>
);
}
}
ReactDOM.render(<Hello />, mountNode);
// AAA
class Hello extends React.Component {
render() {
return(
React.createElement("div", { className: "container" }),
React.createElement("h1", null, "Getting started")
);
}
}
ReactDOM.render(React.createElement(Hello, null), mountNode);
// REACT COMPONENT's NAME HAS TO START WITH UPPER CASE
// if we start with lowercase then react will think that it is html element we are referring to
function logRandom() {
console.log(Math.random());
}
function Button() {
// useState is used for changing element state
// a, b = useState()
// a => state object (getter)
// b => updater function (setter)
// since javascript only allows returning one element at the time, we return an array
// to go around this limit]
// we also need to add const to make it work
// useState(0) will set the setCounter to increment counter value
// useState is a hook, a hook connects the component with a state
const [counter, setCounter] = useState(5);
// we can define function callback to pass it on later but we need to do it inside our component, because
// we need to have access to our getter and setter
const handleClick = () => setCounter(counter + 1);
const handleClick2 = function () {
setCounter(counter + 1);
console.log("test");
}
// to execute any code in JSX code we can use {code}
// events are case sensitive, so we need to type onClick instead of onclick like in regular html!!
// we don't need to invoke the function in {code} block, we just need to pass the pointer to the our function
// it is also possible to define the function on the spot
// return <button onClick={function logRandom() {
// console.log(Math.random());
// }}>{counter}</button>;
// OR as an arrow function
// <button onClick={() => console.log(Math.random())}>{counter}</button>;
return (
// <button onClick={() => setCounter(counter * 2)}>
<button onClick={handleClick2}>
{counter}
</button>);
}
ReactDOM.render(
// single element case
<Button />,
// multiple element case
// exhibit a
[<Button />, <Display />]
// exhibit b
// with DOM parent
<div>
<Button />
<Display />
</div>
// exhibit c
// without DOM parent with react.fragment
<React.Fragment>
<Button />
<Display />
</React.Fragment>
// exhibit d
// without DOM parent without react.fragment
<>
<Button />
<Display />
</>
// exhibit d
// without DOM parent, lazy option
document.getElementById('mountNode'),
);
{{{ var v = 42; }}}
{
// block scope
{
// nested block scope
// let, const
// we use const if reference should not change
// const means constant reference
// not constant value, we can still replace it
// with array and objects content of them might change but reference will not!
// the more consts the better! :)
}
}
function sum(a, b) {
// function scope
}
for (let i = 1; i <= 10; i++) {
// block scope
}
// if we defined i as var then we could access it after the loop!
// Arrow functions
const X = function() {
// this here is the caller of x
}
const Y = () => {
// this is not caller of Y
// it's the same this found in Y's scope
}
// rules
// Regular functions give access to their "calling" environment while arrow functions give access to their "defining" environment
// The value of "this" inside a regular function depends on HOW the function was CALLED (OBJECT THAT MADE THE CALL)
// The value of "this" inside an arrow function depends on where the function was DEFINED
const testerObj = {
func1: function() {
console.log('func1', this);
},
func2: () => {
console.log('func2', this);
}
}
testerObj.func1();
testerObj.func2();
// shorter syntax
const square = a => a * a;
// Object literals
const mystery = 'answer';
const inverseOfPi = 1 / Math.PI;
const obj = {
p1: 10,
p2: 20,
f1() {},
f2: () => {},
[mystery]: 42, //dynamic property, underneath there will be no property called mystery, but there will be one called answer as defined in the mystery variable above and it's value will be 42
inverseOfPi // short syntax
}
console.log(obj.mystery);
// Destructuring
// const PI = Math.PI;
// const E = Math.E;
// const sqrt2 = Math.SQRT2;
const {PI, E, SQRT2} = Math;
// const {Component, Fragment, useState} = require('react');
// useState();
const circle = {
label: 'circleX',
radius: 2
};
// here we extract just the properties that we are interested in from object
const circleArea = ({radius}, {precision = 2} = {}) => (PI * radius * radius).toFixed(2);
console.log(circleArea(circle));
// {precision = 2} = {}
// If we won't provide object that has precision property then it will use empty object that will use default value of 2 as precision
// here we skipped third argument so forth will hold value of 40
const [first, second,, forth] = [10, 20, 30, 40];
console.log(second);
console.log(forth);
// here we want to create new array for elements after the first one
//const [first, ...restOfItems] = [10, 20, 30, 40];
const data = {
t1 = '1',
t2 = '2',
name = 'john'
};
const {t1, t2, ...person} = data;
// shallow copies
const newArray = [...restOfItems];
const newObject = {
...person
};
// Template strings
const s1 = 's1';
const s2 = 's2';
// interpolation, dynamic data
const s3 = `
<div>
${Math.random()}
</div>`;
// Classes
class Person {
constructor(name) {
this.name = name;
}
greet() {
console.log(`Hello, ${this.name}`);
}
}
class Student extends Person {
constructor(name, level) {
super(name);
this.level = level;
}
}
const p1 = new Person("Max");
const p2 = new Student("Tina", "1st grade");
p2.greet = () => console.log("SPECIAL!");
p1.greet();
p2.greet();
function Button(props) {
const handleClick = () => props.onClickFunction(props.increment);
return (
// function callback is available so we just use it from props
// props.onClickFunction(props.increment) is an invocation of a function
// and we need a reference so we need to use arrow syntax or another reference
<button onClick={handleClick}>
+{props.increment}
</button>);
}
function Display(props) {
return (
// nowe message is available in properties, we just need to read it
<div>{props.message}</div>
);
}
// our components always receive props regardless of if we specify (props) or not!
function App() {
// stateful property on parent component so children can access it
// state should be defined as low in tree closest to children that will need that state as possible
const [counter, setCounter] = useState(0);
const incrementCounter = (value) => setCounter(counter + value);
return (
<div>
{/* that's how you comment in JSX */}
{/* props can hold functions as well, because its all object in JS */}
{/* passing value as {5} will cause it to be numeric, "5" will be a string */}
<Button onClickFunction={incrementCounter} increment={1}/>
<Button onClickFunction={incrementCounter} increment={5}/>
<Button onClickFunction={incrementCounter} increment={10}/>
<Button onClickFunction={incrementCounter} increment={100}/>
{/* passing prop to component goes by prop={value}*/}
{/* here we pass counter */}
{/* ONE WAY FLOW OF DATA */}
<Display message={counter}/>
</div>
);
}
ReactDOM.render(
<App />,
document.getElementById('mountNode'),
);
const render = () => {
document.getElementById('mountNode').innerHTML = `
<div>
Hello HTML
<input />
${(new Date).toLocaleTimeString()}
</div>
`;
ReactDOM.render(
React.createElement(
'div',
null,
'Hello React',
React.createElement('input', null),
React.createElement('p', null, (new Date).toLocaleTimeString())
),
document.getElementById('mountNode2'),
);
}
// react only updates what needs to be updated
// with regular dom everything gets updated
// no imperative logic
setInterval(render, 1000);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment