React Hook

About Hooks

useState

useEffect

useRef

useMemo

useCallback

Custom Hook

useContext

useReducer

F&Q

About Hooks

Hook?

讓 Function Component 能用更簡單直覺的方式

使用 React 的功能

React 開發時會遇到的一些問題

  • 狀態邏輯難以共享

  • 複雜組件難以維護

  • Class 難以理解

React Hooks

可以解決這些問題

useState

class Example extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0
    };
  }

  render() {
    return (
      <div>
        <p>You clicked {this.state.count} times</p>
        <button onClick={() => this.setState({ count: this.state.count + 1 })}>
          Click me
        </button>
      </div>
    );
  }
}

Class-Component

Functional-Component

import React, { useState } from 'react';

function Example() {
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

useState

const [狀態, 更新狀態的函式] = useState(初始狀態)

const [count, setCount] = useState(0)

useState

function ExampleWithManyStates() {
  const [count, setCount] = useState(0);
  const [title, setTitle] = useState('標題');
  const [todos, setTodos] = useState([{ text: '我是文字' }]);

多個 state 同時使用

就一直 useState 就好了

useState

// class component
this.state = {name: "Hank", age: 18}
this.setState({age: 30})
console.log(this.state) // {name: "Hank", age: 30}

// hooks example 1
const [user, setUser] = useState({name: "Hank", age:18})
setUser({age: 30})
console.log(user) // {age: 30}

// hooks example 2
const [user, setUser] = useState({name: "Hank", age:18})
setUser({...user, age: 30})
console.log(user) // {name: "Hank", age: 30}

// hooks example 3
const [user, setUser] = useState({name: "Hank", age:18})
setUser((prevUser) => {...prevUser, age: 30})
console.log(user) // {name: "Hank", age: 30}

useState 更新狀態時,不會自動合併物件

每次 setState 的時候給予的值,都會變成全新的狀態

useEffect

class Example extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0
    };
  }

  componentDidMount() {
    document.title = `You clicked ${this.state.count} times`;
  }

  componentDidUpdate(prevProps, prevState) {
    if( prevState.count !== this.state.count ) {
      document.title = `You clicked ${this.state.count} times`;
    }
  }

  render() {
    return (
      <div>
        <p>You clicked {this.state.count} times</p>
        <button onClick={() => this.setState({ count: this.state.count + 1 })}>
          Click me
        </button>
      </div>
    );
  }
}

Class-Component

import React, { useState, useEffect } from 'react';

function Example() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    document.title = `You clicked ${count} times`;
  });

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

Functional-Component

useEffect

useEffect(didUpdate)

useEffect(() => {
  document.title = `You clicked ${count} times`;
});
class Example extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      windowWidth: window.innerWidth
    };
  }

  resizeHandler = () => {
    this.setState({ windowWidth: window.innerWidth });
  };
  
  componentDidMount() {
    window.addEventListener("resize", this.resizeHandler);
  }

  componentWillUnmount() {
    window.removeEventListener("resize", this.resizeHandler);
  }

  render() {
    return (
      <div>
        <p>windowWidth: {this.state.windowWidth}</p>
      </div>
    );
  }
}

Class-Component

import React, { useState, useEffect } from 'react';

function Example() {
  const [windowWidth, setWindowWidth] = useState(window.innerWidth);
  const resizeHandler = () => {
    setWindowWidth(window.innerWidth)
  }

  useEffect(() => {
    window.addEventListener("resize", resizeHandler);
    return () => {
      window.removeEventListener("resize", resizeHandler);
    }
  }, []);

  return (
    <div>
      <p>windowWidth: {windowWidth}</p>
    </div>
  );
}

Functional-Component

useEffect

useEffect(() => {
  window.addEventListener("resize", resizeHandler);
  return () => {
    // 清理函式
    window.removeEventListener("resize", resizeHandler);
  }
}, []);

useRef

Example

import React, { useRef } from 'react';

function Example() {
  const inputEl = useRef(null);

  const clickHandler = () => {
    inputEl.current.focus();
  }

  return (
    <div>
      <input ref={inputEl} type="text" />
      <button onClick={clickHandler}>Click me</button>
    </div>
  );
}

Example

import React, { useRef } from "react";

function Example() {
  const countRef = useRef(0);

  return (
    <div>
      <p>You clicked {countRef.current} times</p>
      <button
        onClick={() => {
          countRef.current += 1;
        }}
      >
        Click me
      </button>
      <button
        onClick={() => {
          alert(countRef.current);
        }}
      >
        Alert
      </button>
    </div>
  );
}

useMemo

Example

import React, { useState, useMemo } from 'react';

function Example() {
  const [count, setCount] = useState(0);

  const square = useMemo(() => {
    return count * count;
  }, [count])

  return (
    <div>
      <p>You clicked {count} times</p>
      <p>{count} * {count} = {square}</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

useCallback

Example

import React, { useState, useCallback } from 'react';

function Example() {
  const [count, setCount] = useState(0);

  const clickHandler = useCallback(() => {
    setCount(count + 1)
  }, [count])

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={clickHandler}>
        Click me
      </button>
    </div>
  );
}

Custom Hook

useContext

useReducer

注意事項

1. 確保 Hooks 執行順序 (重要)

 

2. Hooks 只能用在兩個地方, function component 或 custom hook

 

3. 不用急著把所有組件都改寫成 Hooks, 除非你本來就想要重寫

所有物質都是由原子組成的,當科學家發現原子時,取名叫做 atom(意指不可分割),但後來又在原子裡發現電子的存在,電子的特性甚至更能解釋原子之間的交互作用。

Hooks 之於 Components 就好比電子之於原子, Hooks 並不是新的東西,但它更能表現 Components 之間的運作關係,React 的 Logo 看起來就像是電子繞著原子,其實 Hooks 一直都在,只是我們沒有發現而已

Dan Abramov

React Logo

結束 謝謝

有問題可以提出喔

React Hooks

By 蔡阿貴

React Hooks

  • 535