> Init
> Case of study
+ Step = branch
> Why ? > Before
import React, { Component } from "react";
export default (CatParts) =>
class CatBoddy extends Component {
constructor(props) {
super(props);
this.state = { requestId: 0}
this.onClick = this.onClick.bind(this);
}
onClick(ev) {
const requestId = Math.random().toString(25).substring(10)
this.setState({requestId});
}
render() {
return (
<div className="list">
<button className="btn" onClick={this.onClick}>
Paw here to get random cats
</button>
{<CatParts requestId={this.state.requestId} />}
</div>
);
}
};"Trade-offs":
- Binding
- Super
- Duplicate code
> Why ? > Before > Duplicated code
import React, { Component } from 'react';
import Cat from './Cat';
import catRequest from '../network/catRequest';
class CatList extends Component {
// TODO: use proptypes checker.
constructor(props) {
super(props);
this.state = {
catList: [],
}
}
async componentDidMount () {
const data = await catRequest(9);
this.setState({catList: data});
}
async componentDidUpdate (prevProps, prevState) {
if (prevProps.requestId !== this.props.requestId) {
const data = await catRequest(9);
this.setState({catList: data});
}
}
render() {
return (
<section className='wrapper'>
{this.state.catList.map(cat => <Cat key={cat.id} url={cat.url} />)}
</section>
)
}
}
export default CatList;
> Why ? > Before > Duplicated code solution (HOC) + autobinding + super (Class Fields)
export default (CatParts) =>
class CatBoddy extends Component {
state = {
catList: [],
requestId: 0,
};
async componentDidMount() {
const data = await catRequest(9);
this.setState({ catList: data });
}
// This is done for educational purposes, yes, I know it is not the best use case
async componentDidUpdate(prevProps, prevState) {
if (prevState.requestId !== this.state.requestId) {
const data = await catRequest(9);
this.setState({ catList: data });
}
}
// Class Fields
onClick = (ev) => {
const requestId = Math.random().toString(25).substring(10);
this.setState({ requestId });
}
render() {
return (
<div className="list">
<button className="btn" onClick={this.onClick}>
Paw here to get random cats
</button>
{
<CatParts
requestId={this.state.requestId}
catList={this.state.catList}
/>
}
</div>
);
}
};import React, { Component } from 'react';
import Cat from './Cat';
import CatBoddy from './CatBoddy';
function CatList({catList}) {
return (
<section className='wrapper'>
{catList.map(cat => <Cat key={cat.id} url={cat.url} />)}
</section>
);
}
export default CatBoddy(CatList);
/*
How about if we have more components who receive the same properties?
*/
function CatList({catList}) {
...
}
export default CatBoddy(CatList1);
....
export default CatBoddy(CatListFooter);
export default CatHOC1(CatHOC2(CatHOC3.....))> Why ? > Before > But ... wrapper hell
> Why ? > Before > Reder props ?
> Why ? > overview
import React, { Component } from "react";
export default (CatParts) =>
class CatBoddy extends Component {
constructor(props) {
super(props);
this.state = { requestId: 0}
this.onClick = this.onClick.bind(this);
}
onClick(ev) {
const requestId = Math.random().toString(25).substring(10)
this.setState({requestId});
}
render() {
return (
<div className="list">
<button className="btn" onClick={this.onClick}>
Paw here to get random cats
</button>
{<CatParts requestId={this.state.requestId} />}
</div>
);
}
};- Binding
- Super
- Duplicate code
- Wrapper hell
- Multiple life-cycles
> Why ? > Before vs Hooks
Need state ? = Class
Not State ? = Functional Stateless Components
Not State / State = Function components! *
Functions are simple!
Hooks are functions that let you “hook into” React state and lifecycle features from function components.
> What ? > Hooks
import React, { useState, useEffect } from 'react';
import Cat from './Cat';
import catRequest from "../network/catRequest";
function CatList() {
const [catData, setCatData] = useState([]);
const [requestId, setRequestId] = useState(0);
useEffect(() => {
fetchCats();
}, [requestId]);
async function fetchCats () {
const data = await catRequest(10);
setCatData(data);
}
// fetch more cats
const onClick = (ev) => {
const requestId = Math.random().toString(25).substring(10);
setRequestId(requestId);
}
return (
<div className="list">
<button className="btn" onClick={onClick}>
Paw here to get random cats
</button>
<section className='wrapper'>
{catData.map(cat => <Cat key={cat.id} url={cat.url} />)}
</section>
</div>
);
}
export default CatList;> What ? > Hooks > Basics
const [catData, setCatData] = useState([]);
const [requestId, setRequestId] = useState(0);
...
async function fetchCats () {
const data = await catRequest(10);
setCatData(data);
}
// fetch more cats
const onClick = (ev) => {
const requestId = Math.random().toString(25).substring(10);
setRequestId(requestId);
}> What ? > Hooks > Basics
const [catData, setCatData] = useState([]);
const [requestId, setRequestId] = useState(0);
useEffect(() => {
fetchCats();
}, [requestId]);
async function fetchCats () {
const data = await catRequest(10);
setCatData(data);
}> What ? > Hooks > Basics
subscribe to React context without introducing nesting
import React, { useContext } from "react";
import { GlobalContext } from "../context/GlobalState";
export const Balance = () => {
const { transactions } = useContext(GlobalContext);
const amounts = transactions.map(transaction => transaction.amount);
const total = amounts.reduce((acc, item) => (acc += item), 0).toFixed(2);
return (
<>
<h4>Your Balance</h4>
<h1>${total}</h1>
</>
);
};
> What ? > Hooks > Basics
> Reuse everywhere!
Extract component logic into reusable functions.
export default function useGetCatsData (requestId, catNumber) {
const [catData, setCatData] = useState([]);
useEffect(() => {
fetchCats();
}, [requestId]);
async function fetchCats () {
const data = await catRequest(catNumber);
setCatData(data);
}
return catData;
}function CatList() {
const [requestId, setRequestId] = useState(0);
const catData = useGetCatsData(requestId, 10);
// fetch more cats
const onClick = (ev) => {
const requestId = Math.random().toString(25).substring(10);
setRequestId(requestId);
}
return (
<div className="list">
<button className="btn" onClick={onClick}>
Paw here to get random cats
</button>
<section className='wrapper'>
{catData.map(cat => <Cat key={cat.id} url={cat.url} />)}
</section>
</div>
);
}import React, { useState, useEffect } from 'react';
import Cat from './Cat';
import catRequest from "../network/catRequest";
function CatList() {
const [catData, setCatData] = useState([]);
const [requestId, setRequestId] = useState(0);
useEffect(() => {
fetchCats();
}, [requestId]);
async function fetchCats () {
const data = await catRequest(10);
setCatData(data);
}
// fetch more cats
const onClick = (ev) => {
const requestId = Math.random().toString(25).substring(10);
setRequestId(requestId);
}
return (
<div className="list">
<button className="btn" onClick={onClick}>
Paw here to get random cats
</button>
<section className='wrapper'>
{catData.map(cat => <Cat key={cat.id} url={cat.url} />)}
</section>
</div>
);
}
export default CatList;> Hooks Rules!
> Reuse everywhere!
why react hooks - Tyler Mcginnis : https://www.youtube.com/watch?v=eX_L39UvZes
https://www.slideshare.net/CarlosMafla1/introduccin-a-react-hooks-hooke-me-up
React conf 2018 - https://www.youtube.com/watch?v=dpw9EHDh2bM
https://www.slideshare.net/AikdanaiSidhikosol/react-hooks-101