Add to single HTML: https://reactjs.org/docs/add-react-to-a-website.html
https://reactjs.org/docs/create-a-new-react-app.html
NEXT.js statically server rendered & exporting a static site https://nextjs.org/
ReactDOM - manages everything inside a <div>
Element - immutable (a frame in a movie), to be rendered in a React DOM
JSX - expression that mixes HTML / Component tags and compiles into a function call that returns an Element
Component - act like a pure function that accepts a single props & return an Element
Props - attribute like, read only object passed into component
State
Is syntax extension to Javascript
JSX expression compiles to 'React.createElement()' calls and evaluate to React Elements
Prevents injection attacks by default
const element = (<h1>Hello, {name}</h1>);
JSX expression
Can mix HTML tags or Component with JS
React DOM uses camelCase property nameing instead of HTML attribute naming
Children - just like HTML
{name} : any JS expression in curly braces
recommended: wrap in parentheses (to avoid pitfalls of automatic semicolon insertion)
const element = <div tabIndex="0"></div>;
const element = <img src={user.avatarUrl}></img>;
HTML attributes - can use either "" or {} but not both
Inside HTML there is a (usually just one but can be many) <div> which is the root DOM. Inside it everything is managed by React DOM.
const element = <h1>Hello, world</h1>;
ReactDOM.render(element, document.getElementById('root'));
Are plain, cheap JS objects
Immutable (like a single frame in a movie)
Can represent DOM (HTML) tags or user-defined Component
React DOM take care of rendering (match DOM with React elements)
Rendering is differential - only update what's necessary
Reference: https://reactjs.org/docs/react-component.html
Components accept a Props and return React Elements
All React components must act like pure functions with respect to their props
ALWAYS start with Capital - otherwise treated as DOM tags
function ExampleComponent(props) {
return <h1>Hello, {props.name}</h1>;
}
class ExampleComponent extends React.Component {
render() {
// returns an Element
return <h1>Hello, {this.props.name}</h1>;
}
}
Composition - just like HTML
Pass in
like HTML attributes when using a Component
In Component, an read-only object
Similar to props, but is private and fully controlled by Component (uses class syntax).
Basic rules:
Do not modify directly, use this.setState
the object provided is SHALLOW MERGED into the current state
Can be updated asynchronously. If rely on previous state to calculate next, do not use this.state directly, use this.setState( (state, props) => { /*return new state*/})
DO NOT modify state directly - use this.setState
Form 1: Directly set a value: this.setState( { /*this is a new state */ } )
class Clock extends React.Component {
constructor(props) {
super(props);
this.state = {date: new Date()}; // only place to assign this.state is in constructor
}
render() {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {this.state.date.toLocaleTimeString()}.</h2>
</div>
);
}
}
Form 2: State may be updated asynchronously for performance reason. Therefore DO NOT rely on state values to calculate the next state. Use this.setState((state, props) => { /*returns a new state*/} ); The function accepts state and props and return a new state.
The provided state is MERGED into current state
Parent component may pass down state to child component
Mounting - when component is rendered into DOM for the first time
Unmounting - when component produced DOM is removed
Lifecycle methods - called when lifecycle event occurs
componentDidMount() {
// good place to allocate resource
}
componentWillUnmount() {
// good place to free up resource
}
camelCase - React events are named, rather than lowercase (HTML)
pass a function - rather than a string (in HTML)
<button onClick={activateLasers}>
Activate Lasers
</button>
In a component's internal event, prefer handle event with a method on the class. i.e. "<button onCLick={this.handleClick}>"
NOTE: IMPORTANT:
"this.handleClick", in itself in JS, is just a method. Only calling it with an object can set "this"
however when event is emitted the handler is called as a free function - not a method (so anytime when passing a method as a handler, think about binding "this")
therefore, in the handling method, "this" would be undefined - unless... (see below)
Syntax for binding component internal event:
<button onCLick={this.handleClick}> - "standard", but "this" will be missing in the handler when handler is called (because caller just view it as a function not a method that should be bound)
define the method as handleClick = () => { /*some code*/} (the "public class fields syntax, experimental, requires tools, and https://dev.to/guin/learn-public-class-field-syntax-by-refactoring-a-react-component-njh it says "the class fields are added to the instance itself instead of the prototype. If we create 100 instances, we would be creating 100 new copies of the method!")
<button onClick={() => this.handleClick()}> - the "arrow function" syntax, but may cause re-rendering, not recommended
RECOMMENDED: in constructor, bind the method, i.e. this.handleLoginClick = this.handleLoginClick.bind(this);
Passing extra parameters
<button onClick={(e) => this.deleteRow(id, e)}>Delete Row</button>
<button onClick={this.deleteRow.bind(this, id)}>Delete Row</button>
API Reference: https://reactjs.org/docs/events.html
To prevent default behavior - call event.preventDefault() instead of returning false (HTML)
Ways:
Use JS conditional operators such as "if" and ? : expression
Use variable to hold an element then render it with { theVariable }
Inline (not recommended), for example { logical.expression === true && <h2> some HTML here { another.JS.expression } </h2> }
For a component, return null instead of an element makes it not to render
Ways to do:
Use JS array's "map" method to map array member to array of elements (<li>) then wrap it inside an <ul>
When React receives an array of elements, a "key" property should be given to every element to identify the element for React to track it. Best candidate for "key" is a stable ID. Index as key is NOT recommended.
Note: "key" should be in the element in the array, not necessarily the HTML element
Is class extends React.Component (https://reactjs.org/docs/forms.html#controlled-components)
[CON] "It can sometimes be tedious to use controlled components, because you need to write an event handler for every way your data can change and pipe all of the input state through a React component."
Form elements ( <input><textarea><select>...) keep states
Use component state (setState) as "single source of truth"
Use state value as "value" of input
In React (not behavior of HTML), when "value" is set, it prevents user from changing it (unless "onChange" handles and put back the change). If "value" is set to "undefined" or "null", then user can still change it.l
Listen to change of input, and call "setState" to update state
<select value={this.state.value} onChange={this.handleChange}>
Use "value" in React instead of by children (HTML)
Use "value" in root "select" tag in React instead of "selected" in <option> (HTML)
Add "name" attribute to each element and in handler check "event.target.name"
In this case may use ES6 "computed property name" syntax to update state this.setState({ [event.target.name]:value})
extends React.Component
Keep the source of truth in DOM (whereas controlled component, in state)
Use a ref (React.createRef()) with an input (whereas controlled component use a state as the value)
DO NOT specify "value"
Use "defaultValue"/"defaultChecked" to specify initial value
Pro/Con:
Sometimes easier to integrate with non-React code
"Quick and dirty"
Still should usually use controlled components
<input type="file" /> is always an uncontrolled component.
A popular solution including validation, keeping track of visited fields, and handling form submission.
In React, sharing state is by moving it up to the closest common ancestor of the components that need it. (“lifting state up”)
How to do it:
Use props than states as source of truth
Before: const temperature = this.state.temperature;
After: const temperature = this.props.temperature;
Parent component provides a handler for reporting back input changes in props
onTemperatureChange={this.handleCelsiusChange} />
Report updates through props instead updating state
Before: this.setState({temperature: e.target.value});
After: this.props.onTemperatureChange(e.target.value);
NOTE: "on...Change" is a convention, not a special name
Use special "children" prop
Children element in JSX is passed to component as "props.children", render them using {props.children}
Otherwise use own props to pass children (e.g. left and right of split pane etc.)
Specialized component renders general element with specific props
Would not recommend
CodePen, CodeSandbox, Glitch, or Stackblitz
https://jaredpalmer.com/formik