1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

React hooksでレンダリングをキャンセル(bail out)するテクニック

Posted at

はじめに

多少マニアックですが、useState/useReducerでのbail outに関するメモです。少し前の話になりますが、 https://github.com/facebook/react/pull/14569 のプルリクで入ったものです。

どういうことか

const MyComponent = () => {
  const [person, setPerson] = useState({
    name: 'qiita',
    age: 8,
  });
  // ...
};

というようなコンポーネントがあるときに、useState(person)として同じオブジェクトを渡した場合に再レンダリングされないということになります。当たり前といえば、当たり前なので、別に困ることはないですね。

ちなみに「キャンセル」というのは多少語弊があって、そのuseStateに起因するレンダリングが止まるだけであって、他のuseStateやuseContextがあってそれがレンダリングの起因となったり、そもそも親コンポーネントからレンダリングされる場合は止まりません。逆に、止まったら困ることになります。

どういうときに便利か

useStateの場合は利用シーンがあまりないかもしれませんので、useReducerの場合で考えます。ステートを変更しようと思ったけど実は変更がなかったという場合にレンダリングをしないようにできます。
例えば、ageを加算する例は次のようになります。

const personReducer = (state, action) => {
  if (action.type === 'SET_NAME') {
    return { ...state, name: action.name };
  } else if (action.type === 'ADD_AGE') {
    const newAge = state.age + action.age;
    if (newAge === state.age) {
      // bail out
      return state;
    }
    return { ...state, age: newAge };
  } else {
    throw new Error('no action type found');
  }
};

const MyComponent = () => {
  const [person, dispatch] = useReducer(personReducer, {
    name: 'qiita',
    age: 8,
  });
  // ...
};

人工的な例なので便利さは伝わりにくいかもしれませんが、できることは伝わるのではないでしょうか。

おわりに

"bail out"という用語の理解には苦労しました。React内部の話なので、利用者向けのドキュメントにはどこにも載っておらず。React hooksの知見やベストプラクティスはこれから溜まっていくのではないかと期待しています。

1
1
0

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
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?