見出し画像

React Nativeパフォーマンス向上をHooksで

こんにちは、外資系企業のエンジニアとして働いています。タロイモともうします。

前回はReact Nativeでパフォーマンスを向上するための基礎知識をまとめました。今回は実際にHooksを使いパフォーマンスチューニングをしていきます。

renderItemの無名関数を回避する

FlatListを使用しているときに、FlatListコンポーネントの内側にレンダーアイテムを置くと、親コンポーネントがレンダリングされるたびに、レンダーアイテムもレンダリングされてしまいます。そのため、レンダーアイテムはFlatListの外側に出し、不必要な再レンダリングを防ぎましょう。

Before

export default function ParentComponent() {
  const [childState, setChildState] = useState(0);
	return(
	  <FlatList
		renderItem={
		  ({item})=>(
			<AwesomeChild {...item} onPress={(number)=>{setChildState(number)}} />
		  )}
		keyExtractor={(item)=>`awesome-child-key-${item.id}`}
	  />}
    )
}

After

export default function ParentComponent() {
  const [childState, setChildState] = useState(0);
  //外側に出す。
  const awesomeChildListRenderItem = ({item})=>(<AwesomeChild {...item} onPress={(number)=>{setChildState(number)}} />)
  const awesomeChildListKeyExtractor = (item)=>(`awesome-child-key-${item.id}`);
  
  return(
	<FlatList
		renderItem={awesomeChildListRenderItem}
		keyExtractor={awesomeChildListKeyExtractor}
	/>
  )
}

【参考】https://reactnative.dev/docs/optimizing-flatlist-configuration#avoid-anonymous-function-on-renderitem
【参考】https://dev.to/ltsharma24/performance-optimisation-react-native-with-hooks-a77

React.memoとuseCallBackを使う

React.memo()は()の第二引数に比較関数を置きpropsの値に変化があった場合のみ再レンダリングを行います。そのため、第一引数に指定した関数が再レンダリングされそうになった場合に再レンダリングが必要かどうかをチェックし、必要な場合のみ再レンダリングを行います。

React.memo

//関数
const AwesomeChild =({props})=>{	
	return(
	  <Text>{props.count}</Text>
 )
}
//比較関数
const areEqual=(prevProps, nextProps)=>{
 // prevProps.countがnextProps.countが違えば、falseを返し、再レンダリングする。
 return prevProps.count === nextProps.count
 // そうでなければ、trueを返し、再レンダリングしない。
 return true
}

export default React.memo(AwesomeChild,areEqual)

useCallBackはReact.memoと一緒に使う。

before
ButtonコンポーネントはParentComponentの再レンダリングのたびに一緒に再レンダリングされてしまう。

export default ParentComponent()=>{
  const [pressCount, setPressCount] = useState(0);
   
  const updateButtonPress = useCallback(() => { 
       setPressCount(pressCount + 1);
  }, [pressCount]);

  return (
      <View>
        <Button onPress={updateButtonPress} title="Add count" />
        <Text>{pressCount}</Text>
      </View>
  );
}

after
ChildComponentはParentComponentの再レンダリングのたびに一緒に再レンダリングされることを防ぐ。※onPressしても、ChildComponentのpropsに変化はないので、第二引数はいらない。

const ChildComponent = React.memo((props) => {
  return <Button onPress={props.onPress} title="Add count" />
});

export default ParentComponent()=>{
  const [pressCount, setPressCount] = useState(0);
   
  const updateButtonPress = useCallback(() => { 
       setPressCount(pressCount + 1);
  }, [pressCount]);

  return (
      <View>
        <ChildComponent onPress={updateButtonPress}/>
        <Text>{pressCount}</Text>
      </View>
  );
}

【参考】https://sbfl.net/blog/2019/11/12/react-hooks-introduction/

まとめ

今回はReact Hooksを使いパフォーマンスの向上を行う方法を紹介しました。

今後もReact Nativeのパフォーマンス向上の記事を書いていきたいと思います。

ご精読ありがとうございました。

よろしければサポートお願いします! サポートは、サービスの開発・改良や、記事を書く際の素材費とさせていただきます。 少しでも有益な情報発信をしていけるよう努めてまいります。 是非とも応援よろしくお願いします!!!🙇‍♂️