#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}}
и этого будет достаточно.
Ответ №7:
Я использую react-navigation в течение нескольких месяцев. Но размещение экранов непосредственно в Drawer navigator предотвращает вызов метода willunmount. Сначала поместите экран в stack navigator, затем поместите его в drawer navigator.