React Hooks
Amr Draz
Problem
How to re-use and share component logic?
Higher order components
Render Props
Wrapper Hell
Wrapper Hell
screenshot from react conf talk on hooks
Life cycle logic
Create a class just to add some state
export function Counter({ count, setCount }) {
return <div>
<span>count</span>
<button onClick={() => setCount(count + 1)}>+</button>
<button onClick={() => setCount(count - 1)}>+</button>
</div>
}
export class StatfulCounter extends Component {
constructor(props) {
super(props)
this.state = {
count: 0
}
this.setCount = (count) => {
this.setState({ count })
}
}
render() {
const count = this.state
const setCount = this
return <div>
<span>count</span>
<button onClick={() => setCount(count + 1)}>+</button>
<button onClick={() => setCount(count - 1)}>+</button>
</div>
}
}
Classes are hard for humans but also hard for machines to optamise
Proposal Hooks
See react/rfcs
Experimental
You can try it now in react 16.7-alpha
import React, { Component }
export class StatfulCounter extends Component {
constructor(props) {
super(props)
this.state = {
count: 0
}
this.setCount = (count) => {
this.setState({ count })
}
}
render() {
const count = this.state
const setCount = this
return <div>
<span>count</span>
<button onClick={() => setCount(count + 1)}>+</button>
<button onClick={() => setCount(count - 1)}>+</button>
</div>
}
}
import React, { useState } from "react"
export function StatfulCounter () {
const [count, setCount] = useState(0)
return <div>
<span>count</span>
<button onClick={() => setCount(count + 1)}>+</button>
<button onClick={() => setCount(count - 1)}>+</button>
</div>
}
useHooks
import React, { useState } from "react"
export function StatfulCounter () {
const [state, setState] = useState({ count: 0 })
return <div>
<span>state.count</span>
<button onClick={() => setState({ count: state.count + 1 })}>+</button>
<button onClick={() => setState({ count: state.count - 1 })}>+</button>
</div>
}
useState
function ExampleWithManyStates() {
// Declare multiple state variables!
const [age, setAge] = useState(42);
const [fruit, setFruit] = useState('banana');
const [todos, setTodos] = useState([{ text: 'Learn Hooks' }]);
// ...
}
useState
From docs
import { useState, useEffect, Component } from 'react';
class FriendStatus extends Component {
state = { isOnline: null, count: null }
handleStatusChange = (status) => {
this.setState({ isOnline: status.isOnline });
}
setCounter = (count) => this.setState({ count })
componentDidMount() {
ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
ChatAPI.getMessageCount().then(setCounter)
}
componentWillUnmount() {
ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
}
render() {
const { isOnline, count } = this
if (isOnline === null && count === null ) {
return 'Loading...';
}
return <div>
<span>{count}</span><span>isOnline ? 'Online' : 'Offline'</span>;
</div>
}
}
LifeCycle
import { useState, useEffect } from 'react';
function FriendStatus(props) {
const [isOnline, setIsOnline] = useState(null);
const [count, setCount] = useState(null);
function handleStatusChange(status) {
setIsOnline(status.isOnline);
}
useEffect(() => {
ChatAPI.getMessageCount().then(setCounter)
})
useEffect(() => {
ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
return () => {
ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
};
});
if (isOnline === null && count === null ) {
return 'Loading...';
}
return <div>
<span>{count}</span><span>isOnline ? 'Online' : 'Offline'</span>;
</div>
}
useEffect
import { useState, useEffect } from 'react';
function FriendStatus(props) {
count count = useCounterLogic()
count isOnline = useFriendLogic()
if (isOnline === null && count === null ) {
return 'Loading...';
}
return <div>
<span>{count}</span><span>isOnline ? 'Online' : 'Offline'</span>;
</div>
}
function useCounterLogic() {
const [count, setCount] = useState(null);
useEffect(() => {
ChatAPI.getMessageCount().then(setCounter)
})
return count
}
function useFriendLogic() {
const [isOnline, setIsOnline] = useState(null);
function handleStatusChange(status) {
setIsOnline(status.isOnline);
}
useEffect(() => {
ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
return () => {
ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
};
});
return isOnline
}
useCustom
How Does it work?
React Hooks
By Amr Draz
React Hooks
- 95