从不同导航器(React Native)的另一个屏幕返回时如何刷新屏幕?
How to refresh a screen when returning from another screen of a different navigator (React Native)?
我一直在使用 StackNavigator 实现我的大部分应用程序。现在,我添加了一个 DrawerNavigator,它的一个屏幕从中调用原始 StackNavigator 的另一个屏幕。例如,考虑以下用户可以进行的导航序列:
ScreenA -> ScreenB -> ScreenC
其中ScreenA属于StackNavigator,ScreenB属于DrawerNavigator,ScreenC又属于StackNavigator。为实现这一点,实际上 ScreenA 并不直接调用 ScreenB,而是调用另一个屏幕,其唯一目的是充当属于 DrawerNavigator 的所有屏幕的根。此外,该根在 ScreenProps 中接收 StackNavigator,以便其屏幕稍后可以再次使用 Stack。
现在,如果我在 ScreenC 中并使用“this.props.navigation.goBack()”返回,我会 return 到 ScreenB 中的 DrawerNavigator,因为它称为 ScreenC。 ScreenB 应该刷新其状态,即它应该从数据库重新加载信息,因为该信息可能在 ScreenC 中已更改,因此先前的状态不再有效。
当只使用 StackNavigator 时,我总是设法使用“NavigationEvents”来完成。例如:
import {Component} from 'react'
...
import { NavigationEvents } from 'react-navigation'
class ScreenB extends Component{
// This is the function that loads information from the database (PouchDB)
loadInformation = async() =>{
...
}
render(){
return(
<View>
<NavigationEvents onWillFocus = {payload => this.loadInformation()}/>
<NavigationEvents onDidFocus = {payload => this.loadInformation()}/>
...
</View>
)
}
}
通过此实现,“loadInformation”功能在我第一次进入屏幕时以及在我从子屏幕return访问它时都被激活。但是这次我混合了两个导航器,当 return 从 ScreenC 到 ScreenB 时,“onWillFocus”和“onDidFocus”都没有激活,所以我无法再次进入“loadInformation”功能。我该怎么做?
编辑:
我还尝试在 Redux 存储中保留一个布尔变量,用于确定是否必须激活 ScreenB 的“loadInformation”功能。该变量以真值开头。然后,一旦我进入屏幕 B 并执行该功能,它就会更改为 false。当我导航到 ScreenC 时,在该屏幕中变量再次更改为 true,因此当我返回到 ScreenB 时它再次指示必须执行该函数。
需要在 ScreenB 中使用“componentDidUpdate”函数,该函数会不断检查该变量是真还是假,以便调用“loadInformation”。这解决了问题,但带来了新的问题。当我尝试从 ScreenB 导航到 DrawerNavigator 的另一个屏幕时,它花费了太多时间,因为在转换中重复调用“componentDidUpdate”。所以这个解决方案似乎不可行。
很遗憾,您使用的方法 <NavigationEvents>
已更新。所以,你应该做的是:
class screenA/ screenB/ screenC extends React.Component {
componentDidMount() {
this._unsubscribe = navigation.addListener('focus', () => {
// do something
});
}
componentWillUnmount() {
this._unsubscribe();
}
render() {
// Content of the component
}
}
在您的所有屏幕中使用这些更新的导航事件。希望它能解决您的问题。更多信息See This
我正在回答我自己的问题。
解决方案是使用 Redux 商店中的布尔变量来指示是否必须激活函数“loadInformation”。假设变量名为“loadView”,默认值为“false”,但 ScreenC 在将要关闭时将其设置为“true”,因此我们将 return 转到 ScreenB。
换句话说,ScreenC的文件包含这段代码:
import {Component} from 'react'
import { connect } from 'react-redux'
// Here we import the action that allows to change the value of "loadView"
import { changeLoadView } from '../../redux/actions/popUpActions'
...
class ScreenC extends Component{
...
// Function that is activated automatically when we leave the screen
componentWillUnmount(){
// This is the function that assigns the value "true" to "loadView"
this.props.dispatchChangeLoadView(true)
}
...
}
const mapStateToProps = (state) => {
return {
...
}
}
const mapDispatchToProps = (dispatch) => {
return {
dispatchChangeLoadView: (bool) => dispatch(changeLoadView(bool)),
....
}
}
export default connect(mapStateToProps, mapDispatchToProps)(ScreenC);
在 ScreenB 的文件中我使用了一个“假视图”,它是一个没有直接放在“渲染”函数中但被另一个函数调用的 React 视图(在这种情况下名为“activateLoadInformation”) .该函数 return 是一个空视图,但使用它的原因是因为在它的“return”之前我们可以激活我们想要的 ScreenB 的任何其他函数,在本例中是“loadInformation”。我不知道另一种激活函数的方法,这些函数不会在我们想要的时候任意渲染任何东西。
import {Component} from 'react'
import { connect } from 'react-redux'
...
class ScreenB extends Component{
...
// This is the function that loads information from the database (PouchDB)
loadInformation = async() =>{
this.props.dispatchChangeLoadView(false);
...
}
// Fake view that calls the function "loadInformation"
activateLoadInformation(){
this.loadInformation();
return(<View/>)
}
render(){
return(
<View>
{!this.props.loadView &&
<NavigationEvents onWillFocus = {payload => this.loadInformation()}/>
}
{this.props.loadView &&
this.activateLoadInformation()
}
...
</View>
)
}
}
const mapStateToProps = (state) => {
return {
loadView: state.popUpReducer.loadView,
}
}
const mapDispatchToProps = (dispatch) => {
return {
dispatchChangeLoadView: (bool) => dispatch(changeLoadView(bool)),
....
}
}
export default connect(mapStateToProps, mapDispatchToProps)(ScreenB);
我一直在使用 StackNavigator 实现我的大部分应用程序。现在,我添加了一个 DrawerNavigator,它的一个屏幕从中调用原始 StackNavigator 的另一个屏幕。例如,考虑以下用户可以进行的导航序列:
ScreenA -> ScreenB -> ScreenC
其中ScreenA属于StackNavigator,ScreenB属于DrawerNavigator,ScreenC又属于StackNavigator。为实现这一点,实际上 ScreenA 并不直接调用 ScreenB,而是调用另一个屏幕,其唯一目的是充当属于 DrawerNavigator 的所有屏幕的根。此外,该根在 ScreenProps 中接收 StackNavigator,以便其屏幕稍后可以再次使用 Stack。
现在,如果我在 ScreenC 中并使用“this.props.navigation.goBack()”返回,我会 return 到 ScreenB 中的 DrawerNavigator,因为它称为 ScreenC。 ScreenB 应该刷新其状态,即它应该从数据库重新加载信息,因为该信息可能在 ScreenC 中已更改,因此先前的状态不再有效。
当只使用 StackNavigator 时,我总是设法使用“NavigationEvents”来完成。例如:
import {Component} from 'react'
...
import { NavigationEvents } from 'react-navigation'
class ScreenB extends Component{
// This is the function that loads information from the database (PouchDB)
loadInformation = async() =>{
...
}
render(){
return(
<View>
<NavigationEvents onWillFocus = {payload => this.loadInformation()}/>
<NavigationEvents onDidFocus = {payload => this.loadInformation()}/>
...
</View>
)
}
}
通过此实现,“loadInformation”功能在我第一次进入屏幕时以及在我从子屏幕return访问它时都被激活。但是这次我混合了两个导航器,当 return 从 ScreenC 到 ScreenB 时,“onWillFocus”和“onDidFocus”都没有激活,所以我无法再次进入“loadInformation”功能。我该怎么做?
编辑:
我还尝试在 Redux 存储中保留一个布尔变量,用于确定是否必须激活 ScreenB 的“loadInformation”功能。该变量以真值开头。然后,一旦我进入屏幕 B 并执行该功能,它就会更改为 false。当我导航到 ScreenC 时,在该屏幕中变量再次更改为 true,因此当我返回到 ScreenB 时它再次指示必须执行该函数。
需要在 ScreenB 中使用“componentDidUpdate”函数,该函数会不断检查该变量是真还是假,以便调用“loadInformation”。这解决了问题,但带来了新的问题。当我尝试从 ScreenB 导航到 DrawerNavigator 的另一个屏幕时,它花费了太多时间,因为在转换中重复调用“componentDidUpdate”。所以这个解决方案似乎不可行。
很遗憾,您使用的方法 <NavigationEvents>
已更新。所以,你应该做的是:
class screenA/ screenB/ screenC extends React.Component {
componentDidMount() {
this._unsubscribe = navigation.addListener('focus', () => {
// do something
});
}
componentWillUnmount() {
this._unsubscribe();
}
render() {
// Content of the component
}
}
在您的所有屏幕中使用这些更新的导航事件。希望它能解决您的问题。更多信息See This
我正在回答我自己的问题。
解决方案是使用 Redux 商店中的布尔变量来指示是否必须激活函数“loadInformation”。假设变量名为“loadView”,默认值为“false”,但 ScreenC 在将要关闭时将其设置为“true”,因此我们将 return 转到 ScreenB。
换句话说,ScreenC的文件包含这段代码:
import {Component} from 'react'
import { connect } from 'react-redux'
// Here we import the action that allows to change the value of "loadView"
import { changeLoadView } from '../../redux/actions/popUpActions'
...
class ScreenC extends Component{
...
// Function that is activated automatically when we leave the screen
componentWillUnmount(){
// This is the function that assigns the value "true" to "loadView"
this.props.dispatchChangeLoadView(true)
}
...
}
const mapStateToProps = (state) => {
return {
...
}
}
const mapDispatchToProps = (dispatch) => {
return {
dispatchChangeLoadView: (bool) => dispatch(changeLoadView(bool)),
....
}
}
export default connect(mapStateToProps, mapDispatchToProps)(ScreenC);
在 ScreenB 的文件中我使用了一个“假视图”,它是一个没有直接放在“渲染”函数中但被另一个函数调用的 React 视图(在这种情况下名为“activateLoadInformation”) .该函数 return 是一个空视图,但使用它的原因是因为在它的“return”之前我们可以激活我们想要的 ScreenB 的任何其他函数,在本例中是“loadInformation”。我不知道另一种激活函数的方法,这些函数不会在我们想要的时候任意渲染任何东西。
import {Component} from 'react'
import { connect } from 'react-redux'
...
class ScreenB extends Component{
...
// This is the function that loads information from the database (PouchDB)
loadInformation = async() =>{
this.props.dispatchChangeLoadView(false);
...
}
// Fake view that calls the function "loadInformation"
activateLoadInformation(){
this.loadInformation();
return(<View/>)
}
render(){
return(
<View>
{!this.props.loadView &&
<NavigationEvents onWillFocus = {payload => this.loadInformation()}/>
}
{this.props.loadView &&
this.activateLoadInformation()
}
...
</View>
)
}
}
const mapStateToProps = (state) => {
return {
loadView: state.popUpReducer.loadView,
}
}
const mapDispatchToProps = (dispatch) => {
return {
dispatchChangeLoadView: (bool) => dispatch(changeLoadView(bool)),
....
}
}
export default connect(mapStateToProps, mapDispatchToProps)(ScreenB);