React-native-navigation 从另一个 tabnavigator 更改状态
React-native-navigation Change state from another tabnavigator
我正在使用 react-navigation / TabNavigator,有没有办法在不使用 Redux 或 mobx 的情况下从另一个选项卡更改选项卡的状态?
是的,你可以。它有点复杂,有点老套,可能有一些副作用,但理论上你可以做到。我创建了一个 working example snack here.
在 react-navigation 中,您可以 set parameters 使用路线键的其他屏幕。
When dispatching SetParams, the router will produce a new state that
has changed the params of a particular route, as identified by the key
- params - object - required - New params to be merged into existing route params
- key - string - required - Route key that should get the new params
例子
import { NavigationActions } from 'react-navigation'
const setParamsAction = NavigationActions.setParams({
params: { title: 'Hello' },
key: 'screen-123',
})
this.props.navigation.dispatch(setParamsAction)
为此,您需要了解要传递参数的屏幕的 key
属性。现在这是我们变得混乱的地方。我们可以组合 onNavigationStateChange
and screenProps
道具来获取当前堆栈键,然后将它们作为 属性 传递给我们当前所在的屏幕。
重要提示: 因为 onNavigationStateChange
在应用程序首次启动时不会触发 this.state.keys
将是一个空数组。因此,您需要执行初始导航操作。
例子
class App extends Component {
constructor(props) {
super(props);
this.state = {
keys: []
};
}
onNavigationChange = (prevState, currentState) => {
this.setState({
keys: currentState.routes
});
}
render() {
return(
<Navigation
onNavigationStateChange={this.onNavigationChange}
screenProps={{keys: this.state.keys}}
/>
);
}
}
现在我们可以使用keys
属性获取我们需要的屏幕的key,然后我们可以传递需要的参数。
class Tab1 extends Component {
onTextPress = () => {
if(this.props.screenProps.keys.length > 0) {
const Tab2Key = this.props.screenProps.keys.find((key) => (key.routeName === 'Tab2')).key;
const setParamsAction = NavigationActions.setParams({
params: { title: 'Some Value From Tab1' },
key: Tab2Key,
});
this.props.navigation.dispatch(setParamsAction);
}
}
render() {
const { params } = this.props.navigation.state;
return(
<View style={styles.container}>
<Text style={styles.paragraph} onPress={this.onTextPress}>{`I'm Tab1 Component`}</Text>
</View>
)
}
}
class Tab2 extends Component {
render() {
const { params } = this.props.navigation.state;
return(
<View style={styles.container}>
<Text style={styles.paragraph}>{`I'm Tab2 Component`}</Text>
<Text style={styles.paragraph}>{ params ? params.title : 'no-params-yet'}</Text>
</View>
)
}
}
现在您可以从导航中获取新参数,您可以按原样在您的屏幕中使用它,或者您可以在 componentWillReceiveProps
中更新您的状态。
componentWillReceiveProps(nextProps) {
const { params } = nextProps.navigation.state;
if(this.props.navigation.state.params && params && this.props.navigation.state.params.title !== params.title) {
this.setState({ myStateTitle: params.title});
}
}
更新
现在 react-navigation 支持侦听器,您可以使用它来检测屏幕的焦点或模糊状态。
addListener - Subscribe to updates to navigation lifecycle
React Navigation emits events to screen components that subscribe to
them:
willBlur
- the screen will be unfocused
willFocus
- the screen will focus
didFocus
- the screen focused (if there was a transition, the transition completed)
didBlur
- the screen unfocused (if there was a transition, the transition completed)
文档中的示例
const didBlurSubscription = this.props.navigation.addListener(
'didBlur',
payload => {
console.debug('didBlur', payload);
}
);
// Remove the listener when you are done
didBlurSubscription.remove();
// Payload
{
action: { type: 'Navigation/COMPLETE_TRANSITION', key: 'StackRouterRoot' },
context: 'id-1518521010538-2:Navigation/COMPLETE_TRANSITION_Root',
lastState: undefined,
state: undefined,
type: 'didBlur',
};
如果我明白你想要什么,我会想办法刷新之前的导航屏幕。在我的示例中,我刷新了从相机拍摄的图像 :
屏幕 A
onPressCamera() {
const { navigate } = this.props.navigation;
navigate('CameraScreen', {
refreshImages: function (data) {
this.setState({images: this.state.images.concat(data)});
}.bind(this),
});
}
屏幕 B
takePicture() {
const {params = {}} = this.props.navigation.state;
this.camera.capture()
.then((data) => {
params.refreshImages([data]);
})
.catch(err => console.error(err));
}
我正在使用 react-navigation / TabNavigator,有没有办法在不使用 Redux 或 mobx 的情况下从另一个选项卡更改选项卡的状态?
是的,你可以。它有点复杂,有点老套,可能有一些副作用,但理论上你可以做到。我创建了一个 working example snack here.
在 react-navigation 中,您可以 set parameters 使用路线键的其他屏幕。
When dispatching SetParams, the router will produce a new state that has changed the params of a particular route, as identified by the key
- params - object - required - New params to be merged into existing route params
- key - string - required - Route key that should get the new params
例子
import { NavigationActions } from 'react-navigation'
const setParamsAction = NavigationActions.setParams({
params: { title: 'Hello' },
key: 'screen-123',
})
this.props.navigation.dispatch(setParamsAction)
为此,您需要了解要传递参数的屏幕的 key
属性。现在这是我们变得混乱的地方。我们可以组合 onNavigationStateChange
and screenProps
道具来获取当前堆栈键,然后将它们作为 属性 传递给我们当前所在的屏幕。
重要提示: 因为 onNavigationStateChange
在应用程序首次启动时不会触发 this.state.keys
将是一个空数组。因此,您需要执行初始导航操作。
例子
class App extends Component {
constructor(props) {
super(props);
this.state = {
keys: []
};
}
onNavigationChange = (prevState, currentState) => {
this.setState({
keys: currentState.routes
});
}
render() {
return(
<Navigation
onNavigationStateChange={this.onNavigationChange}
screenProps={{keys: this.state.keys}}
/>
);
}
}
现在我们可以使用keys
属性获取我们需要的屏幕的key,然后我们可以传递需要的参数。
class Tab1 extends Component {
onTextPress = () => {
if(this.props.screenProps.keys.length > 0) {
const Tab2Key = this.props.screenProps.keys.find((key) => (key.routeName === 'Tab2')).key;
const setParamsAction = NavigationActions.setParams({
params: { title: 'Some Value From Tab1' },
key: Tab2Key,
});
this.props.navigation.dispatch(setParamsAction);
}
}
render() {
const { params } = this.props.navigation.state;
return(
<View style={styles.container}>
<Text style={styles.paragraph} onPress={this.onTextPress}>{`I'm Tab1 Component`}</Text>
</View>
)
}
}
class Tab2 extends Component {
render() {
const { params } = this.props.navigation.state;
return(
<View style={styles.container}>
<Text style={styles.paragraph}>{`I'm Tab2 Component`}</Text>
<Text style={styles.paragraph}>{ params ? params.title : 'no-params-yet'}</Text>
</View>
)
}
}
现在您可以从导航中获取新参数,您可以按原样在您的屏幕中使用它,或者您可以在 componentWillReceiveProps
中更新您的状态。
componentWillReceiveProps(nextProps) {
const { params } = nextProps.navigation.state;
if(this.props.navigation.state.params && params && this.props.navigation.state.params.title !== params.title) {
this.setState({ myStateTitle: params.title});
}
}
更新
现在 react-navigation 支持侦听器,您可以使用它来检测屏幕的焦点或模糊状态。
addListener - Subscribe to updates to navigation lifecycle
React Navigation emits events to screen components that subscribe to them:
willBlur
- the screen will be unfocusedwillFocus
- the screen will focusdidFocus
- the screen focused (if there was a transition, the transition completed)didBlur
- the screen unfocused (if there was a transition, the transition completed)
文档中的示例
const didBlurSubscription = this.props.navigation.addListener(
'didBlur',
payload => {
console.debug('didBlur', payload);
}
);
// Remove the listener when you are done
didBlurSubscription.remove();
// Payload
{
action: { type: 'Navigation/COMPLETE_TRANSITION', key: 'StackRouterRoot' },
context: 'id-1518521010538-2:Navigation/COMPLETE_TRANSITION_Root',
lastState: undefined,
state: undefined,
type: 'didBlur',
};
如果我明白你想要什么,我会想办法刷新之前的导航屏幕。在我的示例中,我刷新了从相机拍摄的图像 :
屏幕 A
onPressCamera() {
const { navigate } = this.props.navigation;
navigate('CameraScreen', {
refreshImages: function (data) {
this.setState({images: this.state.images.concat(data)});
}.bind(this),
});
}
屏幕 B
takePicture() {
const {params = {}} = this.props.navigation.state;
this.camera.capture()
.then((data) => {
params.refreshImages([data]);
})
.catch(err => console.error(err));
}