Есть ли функция в react-navigation, которая позволяет мне проверить, каким будет следующий маршрут, прежде чем он обновит пользовательский интерфейс?

#javascript #react-native #react-navigation

#javascript #react-native #react-navigation

Вопрос:

Когда я прокладываю маршрут где-то в своей навигации, я хочу выполнить функцию ДО отображения экрана…эта функция изменит тему приложения. У нас есть onStateChange в NavigationContainer, однако мне нужна функция прослушивания, такая как onBeforeStateChange(): { nextRoute, currentRoute }

Пример сценария маршрутизации:

  1. Начните с: Домашняя страница (тема: Главная — Цвета: черный, белый)
  2. Route to: Profilepage (они: Profile — Цвета: синий, белый)
  3. Маршрут обратно на: домашнюю страницу (тема: Главная — Цвета: черный, белый)

Я смог воспроизвести эту функциональность, используя NavigationContainer.onStateChange prop, который позволяет мне использовать следующую логику для изменения темы на основе маршрута:

 <NavigationContainer
      ref={navigationRef}
      onReady={() =>
        (routeNameRef.current = navigationRef.current.getCurrentRoute().name)
      }
      onStateChange={() => {
        /**
         * The below logic ensures the right theme is being used.
         * This func can hold any GOOGLE ANALYTICS methods.
         */
        const previousRouteName = routeNameRef.current;
        const currentRouteName = navigationRef.current.getCurrentRoute().name;

        if (
          previousRouteName !== currentRouteName amp;amp;
          AVAILABLE_THEMES.includes(currentRouteName)
        ) {
          setTheme(currentRouteName);
        }

        routeNameRef.current = currentRouteName;
      }}>
  

Этот фрагмент кода работает нормально, ЗА исключением того факта, что происходит задержка при смене темы. Новая тема устанавливается ПОСЛЕ изменения состояния, а не только перед его изменением. Если бы я смог запустить аналогичную функцию componentWillReceiveProps в моем NavigationContainer, то это позволило бы мне изменить тему ДО отображения следующего маршрута (устраняя задержку смены темы, которая выглядит некрасиво)

setTheme(); Метод взят из специального компонента. Вот поставщик контекста HOC и React, который я использую:

 import React, { createContext, useContext, useState } from 'react';
import { THEMES } from 'theme/colors';


const ThemeContext = createContext();

const ThemeContextProvider = ({ children }) => {
  const [themeID, setThemeID] = useState(THEMES[0].key);

  return (
    <ThemeContext.Provider value={{ themeID, setThemeID }}>
      {children}
    </ThemeContext.Provider>
  );
};

const withTheme = (Component) => {
  return (props) => {
    const { themeID, setThemeID } = useContext(ThemeContext);
    const getTheme = (tID) => THEMES.find((t) => t.key === tID);
    const setTheme = (tID) => setThemeID(tID);
    let theme = getTheme(themeID);
    // Return a default theme if none was found
    if (!theme) {
      theme = THEMES[0];
    }

    return (
      <Component {...props} themes={THEMES} theme={theme} setTheme={setTheme} />
    );
  };
};
  

Моя домашняя страница и страница профиля оба обернуты в withTheme HOC. На данный момент тема изменится ПОСЛЕ изменения состояния навигации, я бы хотел иметь возможность изменить тему НЕПОСРЕДСТВЕННО ПЕРЕД переходом к следующему экрану (вместо того, чтобы она менялась после фактического отображения следующего экрана)

Вопросы:

  • Я слишком усложнил задачу, пытаясь обработать тематизацию на уровне react-navigation, ИЛИ я на правильном пути?

Ответ №1:

Вы можете изменить тему, вызвав функцию, которая изменяет цвет темы непосредственно перед вызовом prop.navigation.navigate(«Home»).

Если вы используете Button / Touchables / Pressable для навигации. Вы можете вызвать функцию смены темы в реквизите onPress перед вызовом функции navigation.navigate(). Это определенно изменит тему перед загрузкой нового экрана. Если тема изменится до изменения экрана. Вы можете установить функцию индикатора загрузки перед функцией темы. Итак, структура следующая:

  1. setIsLoading(true) // показывает индикатор загрузки
  2. changeTheme() // изменяет тему, пока отображается индикатор загрузки.
  3. navigation.navigate («Главная страница») // изменяет экран

И чтобы убедиться, что они выполняются именно в таком порядке, поскольку JavaScript асинхронен, вы можете выполнять функции Promises или обратные вызовы, чтобы они ожидали возврата текущей функции перед запуском следующей функции.

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

 import { useFocusEffect } from '@react-navigation/native';

useFocusEffect(
    React.useCallback(() => {
      const changeTheme = changeThemeColor(() => {  ...Theme function logic... });
      return () => changeTheme();
    }, [])
  );
  

Эта функция запускается, когда экран попадает в фокус.

Вы также можете добавить индикатор загрузки, чтобы скрыть экран, пока функция темы выполняется после загрузки экрана, и отобразить экран после возврата функции темы. Это легко достигается с помощью React.useState()