2022-04-30 10:58:12 +02:00
|
|
|
# React
|
|
|
|
|
|
|
|
## Components
|
|
|
|
|
|
|
|
There are two types of react components:
|
|
|
|
|
|
|
|
- Function Components
|
|
|
|
- Class Components
|
|
|
|
|
|
|
|
Both types can be stateful and have side effects or be purely presentational.
|
|
|
|
|
|
|
|
```jsx
|
|
|
|
// functional component
|
|
|
|
const Component = (props) => {
|
|
|
|
return (
|
|
|
|
<domElementOrComponent... />
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
// class component
|
|
|
|
class Component extends React.Component {
|
|
|
|
return (
|
|
|
|
<domElementOrComponent... />
|
|
|
|
);
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
*NOTE*: a component name *must* start with an uppercase letter.
|
|
|
|
|
|
|
|
Every components has two inputs: *props* and *state*. The props input is explicit while the state is implicit.
|
|
|
|
State is used to determine the changes and when to re-render.
|
|
|
|
Within the component state can be changed while the props object represent fixed input values.
|
|
|
|
|
|
|
|
JSX syntax can represent HTML but gets converted to pure JavaScript before being sent to the browser:
|
|
|
|
|
|
|
|
```js
|
|
|
|
// JSX
|
|
|
|
const element = (
|
|
|
|
<h1 className="greeting">Hello, world!</h1>
|
|
|
|
);
|
|
|
|
|
|
|
|
// compiled JS shipped to browser
|
|
|
|
const element = React.createElement(
|
|
|
|
'h1', // HTML tag name
|
|
|
|
{className: 'greeting'}, // attrs as JSON
|
|
|
|
'Hello, world!' // tag content (can be nested component)
|
|
|
|
);
|
|
|
|
```
|
|
|
|
|
|
|
|
### App Entry-point
|
|
|
|
|
|
|
|
```js
|
|
|
|
const container = document.getElementById('root')!;
|
|
|
|
const root = createRoot(container);
|
|
|
|
|
|
|
|
const element = <h1s>Hello World</h1>
|
|
|
|
root.render(element)
|
|
|
|
```
|
|
|
|
|
|
|
|
### Dynamic Expressions
|
|
|
|
|
|
|
|
```js
|
|
|
|
<tag>{expression}</tag> // expression is evaluated an it's result is displayed
|
|
|
|
<tag onEvent={funcReference}>{expression}</tag>
|
|
|
|
<tag onEvent={() => func(args)}>{expression}</tag>
|
|
|
|
```
|
|
|
|
|
|
|
|
### Props
|
|
|
|
|
|
|
|
```js
|
|
|
|
<Component propName={value} /> // pass a value the component
|
|
|
|
<Component propName={funcReference} /> // pass a function to the component
|
|
|
|
|
|
|
|
function Component(props) {
|
|
|
|
// use props with {props.propName}
|
|
|
|
}
|
|
|
|
|
|
|
|
class Component extends React.Component{
|
|
|
|
// use props with {this.props.propName}
|
|
|
|
render()
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
### Simple Function Component
|
|
|
|
|
|
|
|
```js
|
|
|
|
// Button.js
|
|
|
|
import { useState } from "react";
|
|
|
|
|
|
|
|
function Button() {
|
|
|
|
const [count, setCount] = useState(0); // hook
|
|
|
|
|
|
|
|
const handleCLick = () => setCount(count + 1); // logic
|
|
|
|
|
|
|
|
// JSX
|
|
|
|
return (
|
|
|
|
<button onClick={handleCLick}>
|
|
|
|
{count}
|
|
|
|
</button>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
export default Button;
|
|
|
|
```
|
|
|
|
|
|
|
|
### Simple Class Component
|
|
|
|
|
|
|
|
```js
|
|
|
|
class Button extends React.Component {
|
|
|
|
|
|
|
|
state = {count: 0};
|
|
|
|
//or
|
|
|
|
constructor(props) {
|
|
|
|
super(props);
|
|
|
|
this.state = {count: 0};
|
|
|
|
}
|
|
|
|
|
|
|
|
componentDidMount() {} // called on successful component mount
|
|
|
|
|
|
|
|
handleClick = () => {
|
|
|
|
this.setState({ count: this.state.count + 1 });
|
|
|
|
}
|
|
|
|
// or
|
|
|
|
handleClick = () => {
|
|
|
|
this.setState((state, props) => ({ count: state.count + props.increment }) );
|
|
|
|
}
|
|
|
|
|
|
|
|
render(){
|
|
|
|
return (
|
|
|
|
<button onClick={this.handleClick}>
|
|
|
|
{this.state.count}
|
|
|
|
</button>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
### Nesting Components
|
|
|
|
|
|
|
|
```js
|
|
|
|
import { useState } from "react";
|
|
|
|
|
|
|
|
function Button(props) {
|
|
|
|
return (
|
|
|
|
<button onClick={props.onClickFunc}>
|
|
|
|
+1
|
|
|
|
</button>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
function Display (props) {
|
|
|
|
return (
|
|
|
|
<div>{props.message}</div>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
function App() {
|
|
|
|
|
|
|
|
// state must be declare in the outer component it can be passed to each children
|
|
|
|
const [count, setCount] = useState(0);
|
|
|
|
const incrementCounter = () => setCount(count + 1);
|
|
|
|
|
|
|
|
return (
|
|
|
|
<div className="App">
|
|
|
|
<Button onClickFunc={incrementCounter}/>
|
|
|
|
<Display message={count}/>
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
export default App;
|
|
|
|
```
|
|
|
|
|
|
|
|
### User Input (Forms)
|
|
|
|
|
|
|
|
```js
|
|
|
|
function Form() {
|
|
|
|
const [userName, setUserName] = useState("");
|
|
|
|
|
|
|
|
handleSubmit = (event) => {
|
|
|
|
event.preventDefault();
|
|
|
|
// ...
|
|
|
|
}
|
|
|
|
|
|
|
|
return(
|
|
|
|
<form onSubmit={handleSubmit}>
|
|
|
|
<input
|
|
|
|
type="text"
|
|
|
|
value={userName} // controlled component
|
|
|
|
onChange={(event) => setUserName(event.target.value)} // needed to update UI on dom change
|
|
|
|
required
|
|
|
|
/>
|
|
|
|
<button></button>
|
|
|
|
</form>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
### Lists of Components
|
|
|
|
|
|
|
|
```js
|
|
|
|
// ...
|
|
|
|
<div>
|
|
|
|
{array.map(item => <Component key={uniqueID}>)}
|
|
|
|
</div>
|
|
|
|
// ...
|
|
|
|
```
|
|
|
|
|
2022-08-06 10:48:24 +02:00
|
|
|
> **Note**: The `key` attribute of the component is needed to identify a particular item. It's most useful if the list has to be sorted.
|
2022-04-30 10:58:12 +02:00
|
|
|
|
|
|
|
## Hooks
|
|
|
|
|
|
|
|
### `useState`
|
|
|
|
|
|
|
|
Hook used to create a state object.
|
|
|
|
|
|
|
|
`useState()` results:
|
|
|
|
|
|
|
|
- state object (getter)
|
|
|
|
- updater function (setter)
|
|
|
|
|
|
|
|
```js
|
|
|
|
const [state, setState] = useState(default);
|
|
|
|
```
|
|
|
|
|
|
|
|
### `useEffect`
|
|
|
|
|
|
|
|
Hook used to trigger an action on each render of the component or when one of the watched items changes.
|
|
|
|
|
|
|
|
```js
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
// "side effects" operations
|
|
|
|
|
|
|
|
return () => {/* clean up side effect */} // optional
|
|
|
|
}, [/* list of watched items, empty triggers once */]);
|
|
|
|
```
|
|
|
|
|
|
|
|
### Custom Hooks
|
|
|
|
|
|
|
|
```js
|
|
|
|
// hook definitions
|
|
|
|
const useCustomHook = () => {
|
|
|
|
// eventual state definitions
|
|
|
|
|
|
|
|
// eventual function definitions
|
|
|
|
|
|
|
|
// ...
|
|
|
|
|
|
|
|
return { obj1, obj2, ... };
|
|
|
|
}
|
|
|
|
|
|
|
|
const Component(){
|
|
|
|
// retrieve elements from the hook
|
|
|
|
const {
|
|
|
|
obj1,
|
|
|
|
obj2,
|
|
|
|
...
|
|
|
|
} = useCustomHook();
|
|
|
|
}
|
|
|
|
```
|