Denny@LINE Fukuoka

Hooks of Frontend

自己紹介

  • Denny(デニ)
  • LFKのフロントエンドエンジニア
  • 台湾人
  • twitter: @TinyDenny
  • github: abalone0204

今日話すこと

  • 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

Play Game

With Web Tech

Play Game

How?

Web RTC

The process of WebRTC is ...

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.

References

ありがとうございました

フロントエンドノフック

By Denny Ku

フロントエンドノフック

Talk about hook and team

  • 2,385