LoginSignup
0
0

More than 1 year has passed since last update.

【React Native】LinearGradientの中にScrollViewを置くとエラーログを吐かずにクラッシュする

Last updated at Posted at 2022-03-28

最近React Nativeでアプリを作っていたのですが、奇妙なバグに出くわしたのでメモ書き程度に残しておきます。

開発環境

開発環境はExpoです。

package.json
{
  (省略)
  "dependencies": {
    "expo": "~44.0.0",
    "expo-linear-gradient": "^11.0.3",
    "expo-status-bar": "~1.2.0",
    "react": "17.0.1",
    "react-dom": "17.0.1",
    "react-native": "0.64.3",
    "react-native-web": "0.17.1"
  },
  "devDependencies": {
    "@babel/core": "^7.12.9",
    "@types/react": "~17.0.21",
    "@types/react-native": "~0.64.12",
    "typescript": "~4.3.5"
  }
}

スクロールすると落ちる

とある条件下でスクロールビューを動かすと稀にアプリが落ちるという不具合です。
初めてこのバグに気付いた時は普通にスクロールしただけでアプリが落ちたのですが、色々試行錯誤した結果、動画のようにpadding(またはmargin)を設定している画面端でマウスをドラッグしたままクルクルすると再現しやすいことがわかりました。(なんでかはわかりません)
名称未設定.gif

実機検証中にこのバグが発生したので、シミュレータでも再現するか確認してみましたが、再現はしたもののエラーログも何も吐かずにアプリがクラッシュして途方に暮れていました。

再現させるために色々試して気付いたことは

  • スクロールできる状態でないと再現しない
  • ScrollView内のコンテンツがScrollViewに全て収まる状態でオーバースクロールしても再現しない
  • iOSのみ再現する

ということです。

問題のコード

バグが再現するコードです。

App.tsx
import { SafeAreaView, ScrollView, StyleSheet, Text } from 'react-native';
import { LinearGradient } from 'expo-linear-gradient';

export default function App() {
  return (
    <SafeAreaView style={styles.container}>
      <LinearGradient
        style={styles.linearGradient}
        colors={['red', 'yellow']}>
        <ScrollView>
          <Text>
            {省略}
          </Text>
        </ScrollView>
      </LinearGradient>
    </SafeAreaView>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
  },
  linearGradient: {
    width: '100%',
    height: '100%',
    paddingLeft: 30
  }
});

ExpoのログではなくOS側のログを見てもそれらしきエラーログを発見できなかったので、仕方なくどういう条件でバグが再現するのかをしらみ潰しに試していきました。
結論としては、LinearGradientの中にScrollViewを置いている状態でスクロールするとアプリがクラッシュすることがあるようです。

解決策

解決策はシンプルで、LinearGradientにposition: 'absolute'を指定して、LinearGradientの中にコンポーネントをネストさせないようにしました。

App.tsx
import { SafeAreaView, ScrollView, StyleSheet, Text } from 'react-native';
import { LinearGradient } from 'expo-linear-gradient';

export default function App() {
  return (
    <SafeAreaView style={styles.container}>
      <LinearGradient
        style={styles.linearGradient}
        colors={['red', 'yellow']}/>
      <ScrollView>
        <Text>
          {省略}
        </Text>
      </ScrollView>
    </SafeAreaView>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center'
  },
  linearGradient: {
    width: '100%',
    height: '100%',
    position: 'absolute',
    bottom: 0
  }
});

終わりに

かれこれ半年近くReact Nativeをやってきましたが、腑に落ちないようなバグが多い印象があります。
スクロールビューにグラデーションをかけたいというニッチな(?)使い方をする人は少ないかと思いますが、参考になったら嬉しいです。
結局なぜアプリがクラッシュするのかわからないことだけが心残りですが...。(わかる方がいたら教えてください)

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