Размонтировать или повторно отобразить экран в навигаторе ящиков

#react-native #react-navigation

#react-native #react-навигация

Вопрос:

Я только недавно добавил drawer navigator и завернул свои экраны в createDrawerNavigator()

Это мои текущие маршруты:

  • Home.js
  • Post.js
  • Settings.js

Когда пользователь переходит от Home к Post, я передаю параметр, содержащий данные post.

 onPress={() => this.props.navigation.navigate('Post', {postData: postData})}
  

Когда пользователь вернется из Post в Home, сообщение будет размонтировано. и снова смонтировать со свежими данными при нажатии на другую запись.

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

Это моя настройка маршрута:

 import React from "react";
import { createDrawerNavigator, createStackNavigator, createAppContainer } from 'react-navigation';
import Home from './screens/Home';
import Post from './screens/Post';
import Settings from './screens/Settings';
import SideBar from './screens/sidebar';

const Drawer = createDrawerNavigator(
{
    Home: {screen: Home},
    Post: {screen: Post},
    Settings: {screen: Settings}
},
{
    initialRouteName: "Home",
    backBehavior: 'initialRoute',
    contentOptions: {
    activeTintColor: "#e91e63"
    },
    contentComponent: props => <SideBar {...props} />,
}
);

const AppNavigator = createStackNavigator(
    {
    Drawer: {screen: Drawer},
    },
    {
    initialRouteName: "Drawer",
        headerMode: "none",
    }
);

export default createAppContainer(AppNavigator);
  

Что я делаю не так?

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

Ответ №1:

Для тех, кто использует react-navigation v5. Я столкнулся с той же проблемой, что и мой компонент, который не размонтировался с помощью goBack() ссылки на экран в drawer. После небольшого исследования я обнаружил, что в последней версии react-navigation они добавили атрибут unmountonblur в параметры экрана для drawer navigator, по умолчанию его значение равно false, поэтому компонент не отключается. Я использую это, чтобы решить свою проблему.

Вот мой код

 <Drawer.Screen name="ResetLogsStack" component={ResetLogsStack} options={{unmountOnBlur:true}}/>
  

Вот ссылка для этого: unmountonblur

Комментарии:

1. вау .. ты спасаешь мне день .. это идеальный ответ для тех, кто использует версию 5. Спасибо..

2. Для меня сработало как по волшебству… Спасибо, приятель 🙏

3. Для прямой ссылки reactnavigation.org/docs/drawer-navigator/#unmountonblur

4. Работает отлично!!! Спасибо…

Ответ №2:

Я сталкиваюсь с той же проблемой. Я заставил свой экран Post прослушивать событие фокусировки навигации, вызванное react-nativation here вместо componentDidMount .

 import React from 'react';
import { View } from 'react-native';
import { NavigationEvents } from 'react-navigation';

const Post = () => (
  <View>
    <NavigationEvents
      onWillFocus={payload => console.log('will focus',payload)}
      onDidFocus={payload => console.log('did focus',payload)} // 
      onWillBlur={payload => console.log('will blur',payload)}
      onDidBlur={payload => console.log('did blur',payload)}
    />
    {/* 
      Your view code
    */}
  </View>
);
  

С помощью onDidFocus вы можете получить параметры навигации, извлечь данные и / или состояние обновления. При необходимости вы можете очистить состояние экрана с помощью onDidBlur .

В качестве альтернативы, вы можете выполнить императивное кодирование, как этот документ здесь

Обновить :

Кстати, мне интересно, почему вы поставили Post с помощью Drawer? Это просто для того, чтобы в ящике была ссылка, по которой можно получить доступ к странице публикации?

На мой взгляд, вам следует переместить Home и Post в новый стек и сделать Home в качестве начального маршрута. Это гарантирует, что сообщение будет размонтировано после перехода обратно к Home .

Посмотрите мой пример ниже

 const HomeStack = createStackNavigatior({
   Home: {screen: Home},
   Post: {screen: Post},
}, {
   initialRouteName: 'Home', 
   ...
})

const Drawer = createDrawerNavigator(
{
    HomeStack
    Settings: {screen: Settings}
},
{
    initialRouteName: "HomeStack",
    backBehavior: 'initialRoute',
    contentOptions: {
       activeTintColor: "#e91e63"
    },
    contentComponent: props => <SideBar {...props} />,
}
);
  

Комментарии:

1. проверьте мой опубликованный ответ, я думаю, что я это исправил, не уверен, почему!

2. Экраны в createDrawerNavigator смонтированы один раз аналогично Tab. Но для стека переход назад приведет к удалению (размонтированию) верхнего экрана

3. Да, это то, что я сделал, что я делал неправильно, так это перелистывал createDrawerNavigator с createStackNavigator помощью, спасибо, что разъяснили, как они работают.

4. работает, также мне пришлось переместить вызов api, который у меня был при инициализации, useEffect на onDidFocus , чтобы предотвратить двойной вызов api.

5. @panchicore: на тот момент перехват еще не существовал : D

Ответ №3:

Это так react-navigation работает, чтобы противостоять этому, вы можете добавить слушателей, вот так:

 <NavigationEvents
    onDidFocus={payload => { console.log(payload.state.params,'<- this has your new params') }}
/>
  

или

  this.props.navigation.addListener('didFocus', payload=>{console.log(payload)})
  

Проверьте это для получения дополнительной информации

Ответ №4:

Я потерял несколько часов на это после обновления React Navigation с 2.14.2 до 3.11.0. Забавно, что он работал отлично, и после обновления страницы не перерисовывались, что приводило к неправильному языку и не фактическим данным на страницах. Что я обнаружил, так это проблему, экран DrawerNavigator не должен размонтироваться

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

В основном решение было таким, как ожидалось: прослушать событие WillFocus… Просто добавьте это в код вашего компонента, если вы хотите, чтобы он повторно отображался при каждом посещении.

  /**
 * When using React Navigation Component is not umnounted and instead stored in navigator. 
 * We need component to be rerendered during each visit to show right info and language
 */
componentDidMount() {
    //this.props.navigation will come in every component which is in navigator
    focusSubscription = this.props.navigation.addListener(
        'willFocus',
        payload => {
            this.forceUpdate();//Native react function to force rerendering
        }
    );
    this.setState({focusSubscription: focusSubscription});
}

componentWillUnmount() {
    this.state.focusSubscription.remove();
}
  

Ответ №5:

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

Решение:

Я попытался перевернуть createDrawerNavigator() с createStackNavigator() помощью, и это сработало отлично, как и раньше! Мне не нужно использовать события навигации react, обычные события, подобные componentWillUnmount и componentWillMount , работают отлично.

 const MainScreens = createStackNavigator(
{
   Home: {screen: Home},
   Post: {screen: Post},
   Settings: {screen: Settings}
},
{
   initialRouteName: "Home",
   headerMode: "none",
}
);

const AppNavigator = createDrawerNavigator(
{
   Main: {screen: MainScreens},
},
{
   initialRouteName: "Main",
   backBehavior: 'initialRoute',
   contentOptions: {
   activeTintColor: "#e91e63"
   },
   contentComponent: props => <SideBar {...props} />,
}
);

export default createAppContainer(AppNavigator);
  

Не уверен, что в том, что я сделал, что-то не так, но до сих пор все работает нормально.

Ответ №6:

Согласно ответу Мухаммеда Зайна, если вы используете react navigation v5, вы можете перейти непосредственно к экрану ящика с опцией unmountOnBlur

параметры ={{unmountOnBlur: true}}

и этого будет достаточно.

Документы по навигации React

Ответ №7:

Я использую react-navigation в течение нескольких месяцев. Но размещение экранов непосредственно в Drawer navigator предотвращает вызов метода willunmount. Сначала поместите экран в stack navigator, затем поместите его в drawer navigator.