1

Having an issue with my ScrollView. I use it in a couple different places in my application, and most of them are working exactly as expected.

However, in one component it is working very strangely - if I swipe quickly, it will sometimes work, but usually not, and if I swipe gently or only a small amount, it doesn't work at all. I render a couple different things inside the ScrollView, but can't work out why any of them might be causing a problem, and can't spot anything obvious that's different between the one that doesn't work and the others, so I'm really at my wits end!

I am testing it on Android.

Here's what I think are the relevant bits of code for the page, but I've also put the full code below - please let me know if there's any other detail that would be useful:

const wait = (timeout) => {
  return new Promise((resolve) => setTimeout(resolve, timeout));
};

export default function PotluckStandalone(props) {
  const potlucks = useSelector((state) => state.potlucks);
  const potluck = potlucks.find(
    ({ idCode }) => idCode === props.route.params.idCode
  );

  const [refreshing, setRefreshing] = React.useState(false);

  const onRefresh = React.useCallback(() => {
    setRefreshing(true);
    wait(2000).then(() => setRefreshing(false));
  }, []);

  const dispatch = useDispatch();


  const Reply = () => {
    return (
      <View>
        <FlatList
          keyExtractor={(item, index) => index}
          data={potluck.replies}
          renderItem={({ item }) => (
            <View>
              <Card
                containerStyle={{
                  borderRadius: 12,
                  borderWidth: 1,
                  elevation: 0,
                  backgroundColor: "rgba(255,255,255,0.6)",
                  overflow: "hidden",
                }}
                style={{ borderColor: "rgba(255,255,255,0.1)" }}
              >
                <Card.Title>{item.bringer} is bringing...</Card.Title>
                <Card.Divider />
                {item.bringing.map((bringItem, index) => {
                  return (
                    <Text key={index}>
                      {bringItem}
                      {index < item.bringing.length - 2 ? ", " : ""}
                      {index === item.bringing.length - 2 ? " and " : ""}
                    </Text>
                  );
                })}
              </Card>
            </View>
          )}
        />
      </View>
    );
  };

  if (!potluck) {
    return <Text>Loading...</Text>;
  } else {
    return (
      <ImageBackground
        source={require("../images/background.png")}
        style={{ width: "100%", height: "100%", alignItems: "center" }}
      >
        <ScrollView
          style={styles.page}
          refreshControl={
            <RefreshControl refreshing={refreshing} onRefresh={onRefresh} />
          }
        >
          <Card
            containerStyle={{
              borderRadius: 12,
              borderWidth: 1,
              elevation: 0,
              backgroundColor: "rgba(255,255,255,0.6)",
              overflow: "hidden",
            }}
            style={{ borderColor: "rgba(255,255,255,0.1)" }}
          >
            <Card.Title>
              <Text>{potluck.potluckTitle}</Text>
            </Card.Title>
            <Card.Divider />

            <Text>Host: {potluck.potluckHost}</Text>
            <Text>Theme: {potluck.potluckTheme}</Text>
            <Text>
              Essentials:
              {potluck.essentials.map((essential, index) => {
                return (
                  <Text key={index}>
                    {" "}
                    {essential}
                    {index < potluck.essentials.length - 2 ? ", " : ""}
                    {index === potluck.essentials.length - 2 ? " and " : ""}
                  </Text>
                );
              })}
            </Text>
            <Card.Divider />

            <Reply />
          </Card>

          <Bringing
            potluck={potluck}
            setReplySnack={() => setReplySnack(true)}
          />

        </ScrollView>
      </ImageBackground>
    );
  }
}

const styles = StyleSheet.create({
  page: {
    width: "90%",
    paddingTop: 50,
    paddingBottom: 250,
  },
});

Full code here:

import { StatusBar } from "expo-status-bar";
import React, { useState, useEffect } from "react";
import { useSelector } from "react-redux";
import {
  ScrollView,
  View,
  Text,
  FlatList,
  RefreshControl,
  SafeAreaView,
  Button,
  Share,
  ImageBackground,
} from "react-native";
import { useDispatch } from "react-redux";
import { Card } from "react-native-elements";
import Bringing from "./Bringing";
import { updatePotluck } from "../actions/potlucks";
import { render } from "react-dom";
import { StyleSheet } from "react-native";

import Snackbar from "react-native-snackbar-component";

const wait = (timeout) => {
  return new Promise((resolve) => setTimeout(resolve, timeout));
};

export default function PotluckStandalone(props) {
  const potlucks = useSelector((state) => state.potlucks);
  const potluck = potlucks.find(
    ({ idCode }) => idCode === props.route.params.idCode
  );

  const [refreshing, setRefreshing] = React.useState(false);

  const onRefresh = React.useCallback(() => {
    setRefreshing(true);
    wait(2000).then(() => setRefreshing(false));
  }, []);

  const dispatch = useDispatch();

  const [potluckSnackIsVisible, setPotluckSnackIsVisible] = useState(false);
  const [replySnackVisible, setReplySnackVisible] = useState(false);

  React.useEffect(() => {
    props.route.params.success
      ? setPotluckSnackIsVisible(true)
      : setPotluckSnackIsVisible(false);
  }, []);

  const onShare = async () => {
    try {
      const result = await Share.share({
        message: `Join me for a potluck | whatLuck https://whatluck.netlify.app/potlucks/${potluck.idCode}`,
      });
      if (result.action === Share.sharedAction) {
        if (result.activityType) {
          // shared with activity type of result.activityType
        } else {
          // shared
        }
      } else if (result.action === Share.dismissedAction) {
        // dismissed
      }
    } catch (error) {
      alert(error.message);
    }
  };

  const setReplySnack = () => setReplySnackVisible(true);

  const Reply = () => {
    return (
      <View>
        <FlatList
          keyExtractor={(item, index) => index}
          data={potluck.replies}
          //style={styles.flatlist}
          renderItem={({ item }) => (
            <View>
              <Card
                containerStyle={{
                  borderRadius: 12,
                  borderWidth: 1,
                  elevation: 0,
                  backgroundColor: "rgba(255,255,255,0.6)",
                  overflow: "hidden",
                }}
                style={{ borderColor: "rgba(255,255,255,0.1)" }}
              >
                <Card.Title>{item.bringer} is bringing...</Card.Title>
                <Card.Divider />
                {item.bringing.map((bringItem, index) => {
                  return (
                    <Text key={index}>
                      {bringItem}
                      {index < item.bringing.length - 2 ? ", " : ""}
                      {index === item.bringing.length - 2 ? " and " : ""}
                    </Text>
                  );
                })}
              </Card>
            </View>
          )}
        />
      </View>
    );
  };

  if (!potluck) {
    return <Text>Loading...</Text>;
  } else {
    return (
      <ImageBackground
        source={require("../images/background.png")}
        style={{ width: "100%", height: "100%", alignItems: "center" }}
      >
        <ScrollView
          style={styles.page}
          refreshControl={
            <RefreshControl refreshing={refreshing} onRefresh={onRefresh} />
          }
        >
          <Card
            containerStyle={{
              borderRadius: 12,
              borderWidth: 1,
              elevation: 0,
              backgroundColor: "rgba(255,255,255,0.6)",
              overflow: "hidden",
            }}
            style={{ borderColor: "rgba(255,255,255,0.1)" }}
          >
            <Card.Title>
              <Text>{potluck.potluckTitle}</Text>
            </Card.Title>
            <Card.Divider />

            <Button onPress={onShare} title="Invite your friends" />

            <Text>Host: {potluck.potluckHost}</Text>
            <Text>Theme: {potluck.potluckTheme}</Text>
            <Text>
              Essentials:
              {potluck.essentials.map((essential, index) => {
                return (
                  <Text key={index}>
                    {" "}
                    {essential}
                    {index < potluck.essentials.length - 2 ? ", " : ""}
                    {index === potluck.essentials.length - 2 ? " and " : ""}
                  </Text>
                );
              })}
            </Text>
            <Card.Divider />

            <Reply />
          </Card>

          <Bringing
            potluck={potluck}
            setReplySnack={() => setReplySnack(true)}
          />

          <Snackbar
            visible={potluckSnackIsVisible}
            textMessage="Potluck created successfully!"
            autoHidingTime={3000}
          />
          <Snackbar
            visible={replySnackVisible}
            textMessage="Reply posted successfully!"
            autoHidingTime={3000}
          />
        </ScrollView>
      </ImageBackground>
    );
  }
}

const styles = StyleSheet.create({
  page: {
    width: "90%",
    paddingTop: 50,
    paddingBottom: 250,
  },
});
wowandy
  • 1,124
  • 2
  • 10
  • 23
Gordon Maloney
  • 262
  • 1
  • 11
  • 2
    Does this answer your question? [FlatList inside ScrollView doesn't scroll](https://stackoverflow.com/questions/51098599/flatlist-inside-scrollview-doesnt-scroll) – wowandy Oct 27 '21 at 10:34
  • Thanks @wowandy! That definitely makes it a lot better - but it is still a lot less responsive than on my other components. If I swipe quickly, it works well, but if I do it more gently then it isn't picking it up. I'm going to have a look to see if I can find a way to configure how responsive it is. – Gordon Maloney Oct 27 '21 at 10:53
  • Okay, not sure why (!), but if I wrap the ScrollView in a tag, then it works fine - but I have to import TouchableOpacity from react-native, and ScrollView and FlatList from react-native-gesture-handler, or it doesn't work. Thanks for pointing me in the right direction @wowandy! – Gordon Maloney Oct 27 '21 at 11:10

0 Answers0