Как повторно отображать экран при нажатии в React Native Navigation?

У меня есть прямоугольник внутри экрана React Native Navigation, который я хочу анимировать каждый раз, когда пользователь нажимает на этот конкретный экран. Теперь анимация воспроизводится только один раз при первом рендеринге приложения. Я видел несколько решений, которые сработали для других людей для такого рода проблем, но ни одно из них не сработало для меня — приложение не перерисовывается при нажатии. Что я делаю неправильно?

SettingsScreen.js (анимация, которая должна перерисовываться при переключении экрана)

const { width } = Dimensions.get("screen");

const SettingsScreen = ({navigation}) => {
  const isFocused = useIsFocused();
  return (
    <FlatList
      contentContainerStyle = {style.barContainer}
      data = {[1, 2, 3, 4, 5]}
      keyExtractor = {(_, index) => index.toString()}
      renderItem = {() => (
        <ProgressBar isFocused = {isFocused} navigation = {navigation} />
      )}
    ></FlatList>
  );
};

const ProgressBar = ({ navigation, isFocused }) => {
  const barWidth = React.useRef(new Animated.Value(0)).current;

  console.info(barWidth);

  const finalWidth = width / 2;

  React.useEffect(() => {
    const listener = navigation.addListener("focus", () => {
      Animated.spring(barWidth, {
        toValue: finalWidth,
        bounciness: 10,
        speed: 2,
        useNativeDriver: false,
      }).start();
    });

    return listener;
  }, [navigation]);

  return (
    <View style = {style.contentContainer}>
      <Animated.View style = {[style.progressBar, { width: barWidth }]} />
    </View>
  );
};

MainContainer.js (где настраивается вся навигация)

const profileName = "Profile";
const detailsName = "Details";
const settingsName = "Settings";
const profileNameFR = "P";
const detailsNameFR = "D";
const settingsNameFR = "S";

const Tab = createBottomTabNavigator();

export default function MainContainer() {
  const { locale } = useContext(LanguageContext);
  
  return (
    <NavigationContainer>
      <Tab.Navigator
        screenOptions = {({ route }) => ({
          tabBarIcon: ({ focused, color, size }) => {
            let iconName;

            let rn = route.name;

            if (rn === profileName || rn === profileNameFR) {
              iconName = focused ? "person" : "person-outline";
            } else if (rn === detailsName || rn === detailsNameFR) {
              iconName = focused ? "list" : "list-outline";
            } else if (rn === settingsName || settingsNameFR) {
              iconName = focused ? "settings" : "settings-outline";
            }

            return <Ionicons name = {iconName} size = {size} color = {color} />;
          },
          tabBarActiveTintColor: "tomato",
          inactiveTintColor: "grey",
          tabBarStyle: { padding: 10, height: 60 },
          tabBarLabelStyle: { paddingBottom: 10, fontSize: 10 },
          style: { padding: 10 },
        })}
      >  

Какую версию реактивной навигации вы используете?

dazs 17.11.2022 23:40

"@react-navigation/bottom-tabs": "^6.4.0", "@react-navigation/native": "^6.0.13", "@react-navigation/stack": "^6.3.4",

fakermaker 18.11.2022 00:02
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Массив зависимостей в React
Массив зависимостей в React
Все о массиве Dependency и его связи с useEffect.
0
2
121
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Это происходит потому, что FlatList является PureComponent, а это означает, что он не будет повторно отображаться, если props останется прежним. Так что в этом случае попробуйте использовать useIsFocused хук внутри SettingsScreen компонента и передать его ProgressBar в качестве реквизита.

Внутри экрана настроек:

const isFocused = useIsFocused();

...

<FlatList
 ...
 renderItem = {() => <ProgressBar isFocused = {isFocused} />}

Также не рекомендуется использовать хук useIsFocused, потому что это приведет к ненужному повторному рендерингу вашего компонента много раз. Вместо этого вы можете использовать прослушиватель событий для прослушивания события «фокус», например:

React.useEffect(() => {
 const listener = navigation.addListener('focus', () => {
    Animated.spring(barWidth, {
      toValue: finalWidth,
      bounciness: 10,
      speed: 2,
      useNativeDriver: false,
    }).start();
 });

 return listener;
}, [navigation])

Мне трудно понять, как именно работает поддержка isFocused. Кроме того, он перерисовывает страницу несколько раз при смене экрана, но значение barWidth остается прежним, поэтому оно остается прежним, потому что анимация использует хук useRef (согласно моему пониманию, при повторном рендеринге оно должно быть установлено обратно на 0)? Спасибо за ответ, но проблема для меня все еще остается. Я обновил свой код в основном сообщении.

fakermaker 19.11.2022 13:15

Я отмечаю это как правильный ответ, потому что это выглядит правильным методом повторной визуализации экрана при нажатии, что на самом деле было основным вопросом.

fakermaker 19.11.2022 15:40

Другие вопросы по теме