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.state
とthis.setState
の部分の切り出し
$ 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
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
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
内でやってたやつの切り出し
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のルールがあるらしいのでそれ使いましょうとのこと。
その他は後日書く(多分書く)
「Formの度にControlled Componentsに苦しめられていた...」