使用 react-native-navigation 时如何在显示组件时触发事件?
How to trigger an event when a component is shown when using react-native-navigation?
我正在使用带有 react-native-navigation 的 react-native。我想在显示组件时重新加载数据。当用户单击选项卡导航按钮时显示该组件。
我应该使用 React 生命周期事件还是在 react-native-navigation 中有什么可以在用户导航回组件时触发功能?
我正在使用 redux,我不确定它是否可以提供帮助?
此问题涉及 onDisplay
,这似乎正是我要找的。但是我找不到任何关于它的官方文档 - https://github.com/wix/react-native-navigation/issues/130
覆盖 componentWillMount 生命周期方法:
https://facebook.github.io/react/docs/component-specs.html#mounting-componentwillmount
或者只是将功能放在 render 方法中
这是我最终使用的:
export default class RootNavigator extends React.Component {
state = {currentScreen: null}
_onNavigationStateChange(prevState, newState, action) {
// const currentScreen = getCurrentRouteName(currentState)
// const prevScreen = getCurrentRouteName(prevState)
// console.debug('onNavigationStateChange currentScreen=', currentScreen,
// 'prevScreen=', prevScreen, 'action.routeName=', action.routeName)
console.debug('onNavigationStateChange action.routeName=', action.routeName)
this.setState({currentScreen: action.routeName})
}
render() {
return <RootStackNavigator onNavigationStateChange={this._onNavigationStateChange.bind(this)}
screenProps={{currentScreen: this.state.currentScreen}}/>;
}
与屏幕上的 componentDidUpdate()
相结合(它可能会或可能不会执行某些操作,具体取决于 screenProps 的 currentScreen
)。
注意:我不知道 what/where getCurrentRouteName()
是什么,它给了我错误,所以我不使用它,直接使用 action.routeName
。
有关更多信息和讨论,请参阅 https://github.com/react-community/react-navigation/issues/2371 and https://github.com/react-community/react-navigation/issues/51#issuecomment-323536642。
将其作为 'callIfBackToThisRoute'...
export default ( props, call ) => {
if( !props.navigation ) throw 'I need props.navigation'
const thisRoute = props.navigation.state.routeName;
props.navigation.addListener(
'willFocus',
payload => {
if( payload.state.routeName == thisRoute) call(props)
}
);
}
并在您的组件中使用它...
componentDidMount() {
const { doIt } = this.props;
doIt()
callIfBackToThisRoute(
this.props,
(props) => doIt()
)
}
我喜欢 Bruno Reis 提出的解决方案。我调整了我的使其更简单。
class Whatever extends Component {
componentDidMount(){
this.load()
this.props.navigation.addListener('willFocus', this.load)
}
load = () => {
...
}
}
对于RNN v3,经过多次尝试,我终于找到了正确的方法:
componentDidMount() {
this.navigationEventListener = Navigation.events().bindComponent(this);
}
componentWillUnmount() {
if (this.navigationEventListener) {
this.navigationEventListener.remove();
}
}
componentDidAppear() { // Lazy loading data for RNN
if (this.state.routes.length === 0) {
this.getData();
}
}
关键是,事件监听器的绑定是必须的,否则不会触发componentDidAppear()和componentDidDisappear()
当前接受的答案建议使用 react-navigation 解决方案,而不是 react-native-navigation (RNN),所以我会继续并给出我的两分钱。
正如 Stephen Liu 在他的回答中指出的那样,RNN 提供 screen lifecycle methods 在组件出现 (componentDidAppear
) 和消失 (componentDidDisappear
) 时触发。
Stephen 的回答适用于 class 组件,但是在挂钩时代我更喜欢函数组件。所以这就是如何在函数组件中使用 RNN 的屏幕生命周期方法:
import React, { useEffect } from 'react'
import { Navigation } from 'react-native-navigation'
const MyComponent = ({ componentId }) => {
useEffect(() => {
const navListener = Navigation.events().bindComponent(this, componentId)
// remove the listener during cleanup
return () => {
navListener.remove()
}
}, [componentId])
this.componentDidAppear = () => {
// do stuff when component appears
}
this. componentDidDisappear = () => {
// do stuff when component disappears
}
}
重要:MyComponent
需要一个 componentId
道具,如果它是注册的 RNN 屏幕或模态 (Navigation.registerComponent
),它会自动注入.您也可以手动将其从屏幕组件向下传递给您需要的子组件。
奖金:useComponentDidAppear
挂钩
我在我的项目中经常使用 RNN 的 componentDidAppear,所以我制作了一个自定义挂钩,以便在我的函数组件中非常轻松地重用它:
export const useComponentDidAppear = (componentId, callback) => {
useEffect(() => {
const navListener = Navigation.events().bindComponent(this, componentId)
return () => {
navListener.remove()
}
}, [componentId])
this.componentDidAppear = () => {
callback()
}
}
// then use it like this
const SomeScreen = ({ componentId }) => {
useComponentDidAppear(componentId, () => {
// do stuff when the component appears!
})
}
在documentation中显示可以这样添加焦点事件:
import React, { useEffect } from 'react'
const MyComponent = ({ navigation }) => {
useEffect(() => {
const unsubscribe = navigation.addListener('focus', () => {
// do something
console.log('Hello World!')
});
return unsubscribe;
}, [navigation]);
return (
<View>
<Text>MyComponent</Text>
</View>
)
}
export default MyComponent
我在自己的一个项目中遇到过同样的情况,使用 useFocusEffect hook by react navigation 来解决
有关更多信息,您可以参考有关此内容的文档
我正在使用带有 react-native-navigation 的 react-native。我想在显示组件时重新加载数据。当用户单击选项卡导航按钮时显示该组件。
我应该使用 React 生命周期事件还是在 react-native-navigation 中有什么可以在用户导航回组件时触发功能?
我正在使用 redux,我不确定它是否可以提供帮助?
此问题涉及 onDisplay
,这似乎正是我要找的。但是我找不到任何关于它的官方文档 - https://github.com/wix/react-native-navigation/issues/130
覆盖 componentWillMount 生命周期方法: https://facebook.github.io/react/docs/component-specs.html#mounting-componentwillmount 或者只是将功能放在 render 方法中
这是我最终使用的:
export default class RootNavigator extends React.Component {
state = {currentScreen: null}
_onNavigationStateChange(prevState, newState, action) {
// const currentScreen = getCurrentRouteName(currentState)
// const prevScreen = getCurrentRouteName(prevState)
// console.debug('onNavigationStateChange currentScreen=', currentScreen,
// 'prevScreen=', prevScreen, 'action.routeName=', action.routeName)
console.debug('onNavigationStateChange action.routeName=', action.routeName)
this.setState({currentScreen: action.routeName})
}
render() {
return <RootStackNavigator onNavigationStateChange={this._onNavigationStateChange.bind(this)}
screenProps={{currentScreen: this.state.currentScreen}}/>;
}
与屏幕上的 componentDidUpdate()
相结合(它可能会或可能不会执行某些操作,具体取决于 screenProps 的 currentScreen
)。
注意:我不知道 what/where getCurrentRouteName()
是什么,它给了我错误,所以我不使用它,直接使用 action.routeName
。
有关更多信息和讨论,请参阅 https://github.com/react-community/react-navigation/issues/2371 and https://github.com/react-community/react-navigation/issues/51#issuecomment-323536642。
将其作为 'callIfBackToThisRoute'...
export default ( props, call ) => {
if( !props.navigation ) throw 'I need props.navigation'
const thisRoute = props.navigation.state.routeName;
props.navigation.addListener(
'willFocus',
payload => {
if( payload.state.routeName == thisRoute) call(props)
}
);
}
并在您的组件中使用它...
componentDidMount() {
const { doIt } = this.props;
doIt()
callIfBackToThisRoute(
this.props,
(props) => doIt()
)
}
我喜欢 Bruno Reis 提出的解决方案。我调整了我的使其更简单。
class Whatever extends Component {
componentDidMount(){
this.load()
this.props.navigation.addListener('willFocus', this.load)
}
load = () => {
...
}
}
对于RNN v3,经过多次尝试,我终于找到了正确的方法:
componentDidMount() {
this.navigationEventListener = Navigation.events().bindComponent(this);
}
componentWillUnmount() {
if (this.navigationEventListener) {
this.navigationEventListener.remove();
}
}
componentDidAppear() { // Lazy loading data for RNN
if (this.state.routes.length === 0) {
this.getData();
}
}
关键是,事件监听器的绑定是必须的,否则不会触发componentDidAppear()和componentDidDisappear()
当前接受的答案建议使用 react-navigation 解决方案,而不是 react-native-navigation (RNN),所以我会继续并给出我的两分钱。
正如 Stephen Liu 在他的回答中指出的那样,RNN 提供 screen lifecycle methods 在组件出现 (componentDidAppear
) 和消失 (componentDidDisappear
) 时触发。
Stephen 的回答适用于 class 组件,但是在挂钩时代我更喜欢函数组件。所以这就是如何在函数组件中使用 RNN 的屏幕生命周期方法:
import React, { useEffect } from 'react'
import { Navigation } from 'react-native-navigation'
const MyComponent = ({ componentId }) => {
useEffect(() => {
const navListener = Navigation.events().bindComponent(this, componentId)
// remove the listener during cleanup
return () => {
navListener.remove()
}
}, [componentId])
this.componentDidAppear = () => {
// do stuff when component appears
}
this. componentDidDisappear = () => {
// do stuff when component disappears
}
}
重要:MyComponent
需要一个 componentId
道具,如果它是注册的 RNN 屏幕或模态 (Navigation.registerComponent
),它会自动注入.您也可以手动将其从屏幕组件向下传递给您需要的子组件。
奖金:useComponentDidAppear
挂钩
我在我的项目中经常使用 RNN 的 componentDidAppear,所以我制作了一个自定义挂钩,以便在我的函数组件中非常轻松地重用它:
export const useComponentDidAppear = (componentId, callback) => {
useEffect(() => {
const navListener = Navigation.events().bindComponent(this, componentId)
return () => {
navListener.remove()
}
}, [componentId])
this.componentDidAppear = () => {
callback()
}
}
// then use it like this
const SomeScreen = ({ componentId }) => {
useComponentDidAppear(componentId, () => {
// do stuff when the component appears!
})
}
在documentation中显示可以这样添加焦点事件:
import React, { useEffect } from 'react'
const MyComponent = ({ navigation }) => {
useEffect(() => {
const unsubscribe = navigation.addListener('focus', () => {
// do something
console.log('Hello World!')
});
return unsubscribe;
}, [navigation]);
return (
<View>
<Text>MyComponent</Text>
</View>
)
}
export default MyComponent
我在自己的一个项目中遇到过同样的情况,使用 useFocusEffect hook by react navigation 来解决
有关更多信息,您可以参考有关此内容的文档