LoginSignup
8
9

More than 5 years have passed since last update.

React.Hooksを使ってlocal stateを持つstatefulなfunctional Componentを触ってみる

Last updated at Posted at 2018-10-28

:writing_hand: React Hooks

Hooks are a new feature proposal that lets you use state and other React features without writing a class. They’re currently in React v16.7.0-alpha and being discussed in an open RFC.

もうちょっとしたらclass構文を使わずにfunctional componentの中でもstateを扱ったり各レンダリングサイクルに干渉出来るようになるようです。

useState

class構文でやってたthis.statethis.setStateの部分の切り出し

提供されているversion(16.7.0-alpha.0)でsetup
$ mkdir react-useState && cd $_ 
$ mkdir pages && touch pages/index.js && yarn init --yes
$ yarn add react@16.7.0-alpha.0 react-dom@16.7.0-alpha.0 next
pages/index.js
import { useState } from "react";

export default () => {
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>Click me</button>
    </div>
  );
};
起動
$ ./node_modules/.bin/next
等価のコードを書く為にこれまではlocalstateを持つclassを作る必要があって記述量も結構あった
export default class Example extends React.Component {
  state = {
    count: 0,
  };

  constructor(props) {
    super(props);
    this.handleChange = this.handleChange.bind(this);
  }

  handleChange() {
    this.setState({ count: this.state.count + 1 });
  }

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

こういうテクも紹介されてた
import { useState } from "react";

function useFormInput(initValue) {
  const [value, setValue] = useState(initValue);

  const handleChange = e => {
    setValue(e.target.value);
  };

  return {
    value,
    onChange: handleChange,
  };
}

export default () => {
  const name = useFormInput("lidqqq");

  return (
    <input {...name} />
  );
};

こんな感じでカスタムフックを作る場合は関数名のprefixにuseを付けるべしとの公式見解。

useEffect

class構文内のcomponentDidMount, componentDidUpdate, componentWillUnmount内でやってたやつの切り出し

pages/index.js
import { useState, useEffect } from "react";

export default () => {
  const [count, setCount] = useState(0);

  // Similar to componentDidMount and componentDidUpdate:
  useEffect(() => {
    // Update the document title using the browser API
    document.title = `You clicked ${count} times`;
  });

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

useEffectを使うことで、今まで各ライフサイクル単位でその中にどっかりと記述していたロジックを、コンポーネント内に複数のエフェクトを記述して関連する部分ごとに分割できるようです。

import { useState, useEffect } from "react";

function useWindowWidth() {
  if (process.browser) {
    const [width, setWidth] = useState(window.innerWidth);
    useEffect(() => {
      const handleResize = () => setWidth(window.innerWidth);
      window.addEventListener("resize", handleResize);
      return () => {
        window.removeEventListener("resize", handleResize);
      };
    });
    return width;
  }
}

export default () => {
  const width = useWindowWidth();

  return (
    <div>
      {width}
    </div>
  );
};

Hookのルール

  • トップレベルでのみフックを呼び出す。ループやif文、ネストされた関数内でフックを呼び出さない。
  • Reactを利用していないnativeなJavaScript関数からフックを呼び出さない。

eslintのルールがあるらしいのでそれ使いましょうとのこと。

その他は後日書く(多分書く)

:moyai: 「Formの度にControlled Componentsに苦しめられていた...」

8
9
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
9