ReactNativeで速度改善する方法【hooks】

ReactNativeのアプリで速度が遅くなってきたな!と思った時に改善できるポイントをまとめていきます。基本的な方針はレンダリングの数を減らすことを目的としています。

useCallbackを徹底して使う

関数をuseCallbackに書き換えましょう。私は全ての関数をuseCallbackで書いています。

改善前
const test = () => {
    // 中略
}
改善後
const test = useCallback(() => {
    // 中略
},[])

そもそも、useCallbackが何?って人は、まずは下記をなどを参考にして、理解してきてください。

https://react.dev/reference/react/useCallback

useCallbackで関数を定義すると、レンダリングする回数が減ります。useCallbackについて記事はたくさんありますので、ここでは割愛します。

また、コンポーネントの引数に関数を書いている人もいますが、やめましょう。

改善前
<Test
  onPress={() => {
  // ここに長いソースを書く
}}
>
改善後
const onPress = useCallback(() => {
 // 中略
},[])

<Test
  onPress={onPress}
>

改善後のメリットは「みやすくなる」「render回数が減るので速度改善になる」の二つです。

また細かい箇所なのですが、下記のように各ソースをみます。

改善前
const onPress = useCallback(() => {
 // 中略
},[])

retrun (
  <Button
     onPress={() => onPress()}
  />
)

上記も無駄にrenderが走ってしまいます。

改善後
const onPress = useCallback(() => {
 // 中略
},[])

retrun (
  <Button
     onPress={onPress}
  />
)

onPress={() => onPress()}と書くのではなく、onPress={onPress}と書きましょう。

ポイント

・関数は全てuseCallbackで書く

・コンポーネントの引数に関数を書かない(外に出す)

useMemoを使う

計算コストが大きい変数を使うときは、useMemoを使いましょう。

改善前
const image =  () => images.find((image) => image.beforeText === styledText.text)
改善後
  const image = useMemo(
    () => images.find((image) => image.beforeText === styledText.text),
    [images, styledText.text],
  );

ただし、単純な関数の場合、useMemoを呼び出すコストの方が高くなってしまいます。

呼び出す必要がない例

HTML
const flag = count === 1 ? true : false

useMemoを使う必要があるか、ないかをジャッチするのは正直難しいかと思います。私は上記のような単純な1行の三項構文で書けるような時以外の時は、全てuseMemoで書いています。

ポイント

計算コストが重い変数はuseMemoを使う

useStateでなく、useRefを使うべきか検討する

useStateは描写に関係がある変数で使います。描写に関係ない変数はuseRefで定義しましょう。具体的には、コンポーネントを見返してみて return()の中で使われていない変数は全てreactRefに書き換えられるはずです。

下記ソースを試してもらいたいのですが、onPress1は値が増えますが、onPress2は値が増えません。つまりrenderが走っていないのです。その文処理が速くなります。

具体例

const [count, setCount] = React.useState(0);
const countRef = React.useRef(0);

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

const onPress2 = useCallback(() => {
  countRef.current = countRef.current + 1;
}, []);

return (
  <View>
    <Text>{count}</Text>
    <Button title={'useState'} onPress={onPress1} />

    <Text>{countRef.current}</Text>
    <Button title={'useRef'} onPress={onPress2} />
  </View>
);
ポイント

描写に関係ないものはuseStateでなく、useRefを使う

Redux or useContextを多用しない

全ての値をreduxやuseContextで管理している人がいますが、考えを改めましょう。本当にreduxで値を管理する必要があるか?を確認しましょう。redux、useContextは重いです。例えば、RDBに値を持っているなら、毎回RDB取りに行った方が早い場合も多々あります。

まとめ

いろいろ書きましたが、実装している時に速度を意識するのは大変かと思います。速度改善に本腰を入れるのは、実機で触ってみて「ここ遅いな!」と思ってからでいいと思います。この記事は、実際に速度が遅くなったアプリの参考になればなと思っております。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です