こんにちは、アプリ開発担当のエモトです。遊んでいたソシャゲが12月にサービス終了ということで、溜まった石やアイテムを使って、後先考えずに遊んでいます。アニメ作品のゲーム化なのでいつまで続くのか不安でしたが、2年弱も続いたので満足しております。なお、弊社本社近くのラーメン屋でガチャを回すと引きが良いです(個人調べ)。ガチャ好きな皆さまの入社をお待ちしております。
FlatList
で今表示されている item の情報を取得するため、onViewableItemsChanged
を利用したのですが、問題が起こり手間が取られてしまいました。今回はその問題と解決方法を共有したいと思います。なお、以降に提示するコード例は簡易的にしています。
問題
FlatList
で表示されている item を取得しようと onViewableItemsChanged を利用しました。
const onViewableItemsChanged = ({viewableItems}) => { ... } <FlatList onViewableItemsChanged={onViewableItemsChanged} />
すると、エラーが出てきました。しかも、このエラーは常にではなく、ホットリロード時に起こるなど、特殊なエラーでした。
Changing onViewableItemsChanged on the fly is not supported
調べると、
At least one of the viewAreaCoveragePercentThreshold or itemVisiblePercentThreshold is required.
とのことなので、viewabilityConfig
に値を設定しました。
const onViewableItemsChanged = ({viewableItems}) => { ... } const viewabilityConfig = { itemVisiblePercentThreshold: 50, } <FlatList onViewableItemsChanged={onViewableItemsChanged} viewabilityConfig={viewabilityConfig} />
しかしながら、エラーは治りませんでした。
解決
viewabilityConfig の公式ドキュメントを読むと、気になる一文がありました。
This needs to be done in the constructor to avoid following error
リンクされていた issue を読むと、render のタイミングで生成して渡すとダメな仕様でした。解決方法は分かったものの、私は関数コンポーネントで作成していたので、クラスコンポーネントの constructor
に対応するものは何?と悩むことに。いろいろ調べ試すと今回は useRef()
で良いと分かりました。
const onViewableItemsChanged = useRef(({viewableItems}) => { ... }) const viewabilityConfig = useRef({ itemVisiblePercentThreshold: 50, }) <FlatList onViewableItemsChanged={onViewableItemsChanged} viewabilityConfig={viewabilityConfig} />
やっと無事に動きました。私の中に useRef()
に関数を入れる発想はなかったので、時間がかかってしまいました。
まとめ
FlatList
の仕様と、クラスコンポーネントのメソッドを関数コンポーネントで書くにはどうすればいいんだという2つの問題を踏み抜いて、久々に沼ってしまいました。改めて、こういうシーンでは、
- ドキュメントを漁る
- 関数コンポーネントとクラスコンポーネントの比較
に立ち返るのが良いですね。この FlatList
の仕様は他の方でもハマりそうな問題だと思うので、少しでも参考になれば幸いです。