React Basics
21/10/21
Summary
- What is React?
- Live coding
- Bonus
- Redux
- Router
What is react?
A JavaScript library for building user interfaces
As described by reactjs.org
Declarative
component-based
Learn once - Write everywhere
JSX
render() {
return (
<div>
Seconds: {this.state.seconds}
</div>
);
}render() {
return React.createElement(
'div',
null,
'Seconds: ',
this.state.seconds
);
}Some history: class components
class Timer extends React.Component {
constructor(props) {
super(props);
this.state = { seconds: 0 };
}
tick() {
this.setState(state => ({
seconds: state.seconds + 1
}));
}
componentDidMount() {
this.interval = setInterval(() => this.tick(), 1000);
}
componentWillUnmount() {
clearInterval(this.interval);
}
render() {
return (
<div>
Seconds: {this.state.seconds}
</div>
);
}
};import { useEffect, useState } from 'react';
const Timer = () => {
const [seconds, setSeconds] = useState(0);
const tick = () => setSeconds((s) => s + 1);
useEffect(() => {
const interval = setInterval(tick, 1000);
return () => clearInterval(interval);
}, []);
return (
<div>
Seconds: {seconds}
</div>
);
};Component props
class Welcome extends React.Component {
render() {
return (
<h1>Hello, {this.props.user.name}</h1>
);
}
}const Welcome = ({ user }) => (
<h1>Hello, {user.name}</h1>
);const user = { name: 'Toto' }
<Welcome user={user} />
// => <h1>Hello, Toto</h1>Lifecycle hooks
componentDidMount();
shouldComponentUpdate(nextProps, nextState);
render();
componentDidUpdate(prevProps, prevState, snapshot);
componentWillUnmount();Hooks - The new way
import { useState } from 'react';
// Convention: keep the same name between state and setState
// Only argument is the default value
const [count, setCount] = useState(0);import { useEffect } from 'react';
useEffect(
// function executed each time one of the dependency changes
() => {
const timer = setInterval(() => console.log('Toto'), 1000);
// cleanup function
return () => {
clearInterval(timer):
}
},
[] // dependencies array
)Let's play!
$ npx create-react-app my-app


Want more?
Redux
The big picture

const initialState = { value: 0 }
function counterReducer(state = initialState, action) {
// Check to see if the reducer cares about this action
if (action.type === 'counter/increment') {
// If so, make a copy of `state`
return {
...state,
// and update the copy with the new value
value: state.value + 1
}
}
// otherwise return the existing state unchanged
return state
}import { configureStore } from '@reduxjs/toolkit'
const store = configureStore({ reducer: counterReducer })
console.log(store.getState())
// {value: 0}store.dispatch({ type: 'counter/increment' })
console.log(store.getState())
// {value: 1}const increment = () => {
return {
type: 'counter/increment'
}
}
store.dispatch(increment())
console.log(store.getState())
// {value: 2}const selectCounterValue = state => state.value
const currentValue = selectCounterValue(store.getState())
console.log(currentValue)
// 2The easy way
export const store = {
// initial state
state: {
count: 0
},
reducers: {
// handle state changes with pure functions
increment: (state, payload) => ({ ...state, count: state.count + payload }),
decrement: (state, payload) => ({ ...state, count: state.count - payload })
},
effects: (dispatch) => ({
// handle state changes with impure functions.
// use async/await for async actions
async incrementAsync(payload, rootState) {
await new Promise((resolve) => setTimeout(resolve, 1000));
dispatch.count.increment(payload); // Or this.increment(payload);
}
})
};import { init } from "@rematch/core";
import * as models from "./models";
const store = init({ models });
export default store;$ yarn add -E @rematch/coreconst { dispatch } = store;
// state = { count: 0 }
// reducers
dispatch({ type: "count/increment", payload: 1 });
// state = { count: 1 }
dispatch.count.increment(1);
// state = { count: 2 }
// effects
dispatch({ type: "count/incrementAsync", payload: 1 });
// state = { count: 3 } after delay
dispatch.count.incrementAsync(1);
// state = { count: 4 } after delayimport React from "react";
import ReactDOM from "react-dom";
import { Provider, connect } from "react-redux";
import store from "./store";
const Count = ({ count, increment, incrementAsync }) => (
<div>
The count is {count}
<button onClick={increment}>increment</button>
<button onClick={incrementAsync}>incrementAsync</button>
</div>
);
const mapState = (state) => ({
count: state.store.count,
});
const mapDispatch = (dispatch) => ({
increment: () => dispatch.store.count.increment(1),
incrementAsync: () => dispatch.store.count.incrementAsync(1),
});
export default connect(mapState, mapDispatch)(Count);Router
$ yarn add -E react-router-domimport React from "react";
import {
BrowserRouter as Router,
Switch,
Route,
Link
} from "react-router-dom";
import { About, Home, Users } from './pages';
const App = () => (
<Router>
<div>
<nav>
<Link to="/">Home</Link>
<Link to="/about">About</Link>
<Link to="/users">Users</Link>
</nav>
<Switch>
<Route path="/about">
<About />
</Route>
<Route path="/users">
<Users />
</Route>
<Route path="/">
<Home />
</Route>
</Switch>
</div>
</Router>
);React Basics
By Simon Roussel
React Basics
- 98