26
12

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 3 years have passed since last update.

useStateとuseReducerの関係(どっちが強力?同じ?わずかな違い?決定的な違い?)

Last updated at Posted at 2019-12-03

はじめに

React HooksのuseStateとuseReducerに関する小ネタです。

useStateはuseReducerで実装されている

内部実装ではuseStateはuseReducerで実装されていると、どこかに書いてありました。こちらのブログ記事にuserlandでの実装例が載っています。

const stateReducer = (prevState, newState) =>
  typeof newState === 'function' ? newState(prevState) : newState;

const stateInitializer = initialValue =>
  typeof initialValue === 'function' ? initialValue() : initialValue;

const useState = initialValue =>
  useReducer(stateReducer, initialValue, stateInitializer);

こんな感じになります。

つまり、useStateでできることは全てuseReducerでもできるということです。では、useReducerだけでしかできないことはあるのでしょうか。

useReducerはuseStateでも実装できる

実は、useReducerはuseStateでも実装できます。こちらのブログ記事にuserlandでの実装例があります。

const useReducer = (reducer, initialArg, init) => {
  const [state, setState] = useState(
    init ? () => init(initialArg) : initialArg,
  );
  const dispatch = useCallback(
    action => setState(prev => reducer(prev, action)),
    [reducer],
  );
  return useMemo(() => [state, dispatch], [state, dispatch]);
};

こんな感じになります。つまり、機能的には同等ということになります。

実はわずかな違いがある

こちらのツイートにあるように、useReducerではinitArgとinitが分離されているため、initをpropsに依存しないように書くことができます。これにより、hookの外側で関数定義することもできますし、inline関数で書いたとしてもJavaScriptのランタイムエンジンで最適化される可能性が高いです。

決定的な違いもあるにはある

お勧めしませんが、useReducerには非常に特殊な利用法もあります。それはreducerをコンポーネント内で定義できることです。reducerをコンポーネント内で定義すると未来のpropsを読み込めちゃいます。"cheat mode"と呼ばれたりします。

詳細は、こちらのブログ記事のセクションをご参照ください。

追記(12/4)

このcheat modeは上記のuserland実装では再現できていないですね。

おわりに

小ネタにしようかと思っていましたが、書き始めたらマニアックなネタになってしまいました。楽しんでくれた方がいらしたら幸いです。

26
12
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
26
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?