Denny@LINE Fukuoka
Hooks of Frontend
自己紹介
- Denny(デニ)
- LFKのフロントエンドエンジニア
- 台湾人
- twitter: @TinyDenny
- github: abalone0204
![](https://s3.amazonaws.com/media-p.slid.es/uploads/903588/images/5555494/CkIIo8C3_400x400.jpg)
今日話すこと
- Brief introduction to hooks
- Why hooks matter
- Almost-real-world Example
- Can we do better?
Brief Introduction to Hooks
hooksとは?
Shareable Stateful Logic
Let you hook to React features
in function component
state
setState
Disclaimer:
more detail introduction in Dan's talk in react conf
Problem
- No simpler stateful primitive than a class component
import React from 'react'
const User = (props) => {
return (
<div>
<p>{props.name}</p>
</div>
)
}
import React from 'react'
class User extends React.Component {
constructor(props) {
super(props)
this.state = { name: 'Hakata' }
this.handleInput = this.handleInput.bind(this)
}
handleInput(event) {
this.setState({name: event.target.value})
}
render() {
return (
<div>
<p>{this.state.name}</p>
<input
type="text"
value={this.state.name}
onChange={this.handleInput}
/>
</div>
)
}
}
?
- What we need is: `state` and `setState` in function component
- Assume we have these variables in function component
- Hook is the bridge that let you let you access the `state` and `setState`
import React from 'react'
const User = (props) => {
return (
<div>
<p>{props.name}</p>
</div>
)
}
import React from 'react'
class User extends React.Component {
constructor(props) {
super(props)
this.state = { name: 'Hakata' }
this.handleInput = this.handleInput.bind(this)
}
handleInput(event) {
this.setState({name: event.target.value})
}
render() {
return (
<div>
<p>{this.state.name}</p>
<input
type="text"
value={this.state.name}
onChange={this.handleInput}
/>
</div>
)
}
}
import React from 'react'
const User = ( ) => {
const name = ??
const setName = ??
function handleInput(event) {
setName(event.target.value)
}
return (
<div>
<p>{name}</p>
<input
type="text"
value={name}
onChange={handleInput}
/>
</div>
)
}
import React, { useState } from 'react'
const User = ( ) => {
const [name, setName] = useState('Hakata')
function handleInput(event) {
setName(event.target.value)
}
return (
<div>
<p>{name}</p>
<input
type="text"
value={name}
onChange={handleInput}
/>
</div>
)
}
this.state = { name: 'Hakata' }
this.setState({name: event.target.value})
Step by step to hook
import React from 'react'
class User extends React.Component {
constructor(props) {
super(props)
this.state = { name: 'Hakata' }
this.handleInput = this.handleInput.bind(this)
}
componentDidMount() {
document.title = this.state.name
}
componentDidUpdate() {
document.title = this.state.name
}
handleInput(event) {
this.setState({name: event.target.value})
}
render() {
return (
<div>
<p>{this.state.name}</p>
<input
type="text"
value={this.state.name}
onChange={this.handleInput}
/>
</div>
)
}
}
import React from 'react'
import { useState } from 'react'
const User = ( ) => {
const [name, setName] = useState('Hakata')
function handleInput(event) {
setName(event.target.value)
}
return (
<div>
<p>{name}</p>
<input
type="text"
value={name}
onChange={handleInput}
/>
</div>
)
}
componentDidMount() {
document.title = this.state.name
}
componentDidUpdate() {
document.title = this.state.name
}
More complicated hook
import React from 'react'
import { useState, useEffect } from 'react'
const User = ( ) => {
const [name, setName] = useState('Hakata')
useEffect(() => {
document.title = name
})
function handleInput(event) {
setName(event.target.value)
}
return (
<div>
<p>{name}</p>
<input
type="text"
value={name}
onChange={handleInput}
/>
</div>
)
}
Recap for a sec
- Hooks are just function.
- What can we do for function?
- Extract the common part.
Let's extract the common part
import React from 'react'
import { useState, useEffect } from 'react'
const User = ( ) => {
const [name, setName] = useState('Hakata')
useEffect(() => {
document.title = name
})
function handleInput(event) {
setName(event.target.value)
}
return (
<div>
<p>{name}</p>
<input
type="text"
value={name}
onChange={handleInput}
/>
</div>
)
}
const [name, setName] = useState('Hakata')
useEffect(() => {
document.title = name
})
function handleInput(event) {
setName(event.target.value)
}
{name}
value={name}
onChange={handleInput}
// This is what we call "Custom Hook"
const useUser = (initVal) => {
const [value, setValue] = useState(initVal)
useEffect(() => {
document.title = value
})
function handleChange(event) {
setValue(event.target.value)
}
return { value, onChange: handleChange }
}
const user = useUser('Hakata')
{user.value}
value={user.value}
onChange={user.onChange}
const user = useUser('Hakata')
{user.value}
{...user}
Review
- State hooks, effect hooks, custom hooks
- They are just functions
- Only logic, no jsx, no presentation layer related
Why Hooks matter?
Truly separate Presentation and logic
-
↑Reusability
-
↑Productivity
-
↑Easy to cooperate
LFK's
Hackthon Project
Something is complex enough
Idea
![](https://s3.amazonaws.com/media-p.slid.es/uploads/903588/images/5549293/tv.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/903588/images/5549292/nintendo.png)
Play Game
With Web Tech
![](https://s3.amazonaws.com/media-p.slid.es/uploads/903588/images/5549293/tv.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/903588/images/5549292/nintendo.png)
Play Game
![](https://s3.amazonaws.com/media-p.slid.es/uploads/903588/images/5549298/iphone.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/903588/images/5549299/browsers.png)
How?
Web RTC
![](https://s3.amazonaws.com/media-p.slid.es/uploads/903588/images/5549308/webrtcv.png)
The process of WebRTC is ...
![](https://s3.amazonaws.com/media-p.slid.es/uploads/903588/images/5555275/github.com_abalone0204_BossRTC_blob_master_client_src_hooks_useSinglePeer.ts.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/903588/images/5555278/github.com_abalone0204_BossRTC_blob_master_client_src_hooks_useSinglePeer.ts.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/903588/images/5555279/useRoom.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/903588/images/5555285/useSSE.png)
With hook
const Console = () => {
const peer = useWebRTCPeer()
return (
<div>
<h2>
{peer.status} {/*Connected or not*/}
</h2>
</div>
)
}
const Monitor = () => {
const peer = useWebRTCPeer()
return (
<div>
<GameLogicHandler data={peer.receivedData}>
</div>
)
}
DEMO: BossRTC
With Hooks
- Separate the logic part
- Easy to mock (Just make a mock hook)
- Speed up development
Team
- Different projects
- Communication
- Meet people from all over the world
- Environment
- Don't know anything about Japanese
- Don't even speak English when working in Taiwan
Join Us!
Can we do better?
Hooks can be better
- `use*` is not a reliable way.
- Tracked by order, so nested call can't be done.
- Tricky when testing.
- RFC
Take away
- Make logic more shareable
- A new way to cooperate
- Looking inside React, Vue. This is a good trend in front-end.