如何在选项卡导航器的屏幕之间传递数据,当在第一个屏幕中按下按钮而不被路由到第二个屏幕时?
How to pass data between the screens of a tab navigator, when pressing a button in the 1st screen and WITHOUT being routed to the 2nd screen?
我有一个带有 2 个屏幕的底部选项卡导航器:Screen1 和 Screen2。
在 Screen1 中,有一个 FlatList 显示“水果”列表的内容:
它由一个项目和旁边的“添加”按钮组成。
当按下按钮时,该项目将显示在 Screen2 中。
我想在按下“添加”按钮时将 Screen1 中“水果”列表中的项目传递到 Screen2,而不自动路由到 Screen2。
到目前为止,我可以使用以下方法将项目从 Screen1 传递到 Screen2:navigation.navigate("Screen2", {item}),但它会自动将我带到 Screen2,这不是我想要的。
我觉得navigationprop的dispatch方法可以解决这个问题,但是不知道怎么用!
我正在使用 React Native 0.65 和 React Navigation 6.x。
调度方法的官方文档如下:
https://reactnavigation.org/docs/navigation-prop/#dispatch
提前致谢。
这是我的代码:
import React from 'react';
import { Text, View, FlatList, Button, StyleSheet } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import Constants from 'expo-constants';
const fruits = [
'apples',
'watermelons',
'tomatoes',
'pomegranates',
'strawberries'
];
function Screen1({ navigation }) {
const renderItems = ({ item }) => {
return (
<View style={styles.item_container}>
<Text style={styles.text}>{item}</Text>
<Button
title="add"
onPress={() => navigation.navigate('Screen2', { item })}
/>
</View>
);
};
return (
<View style={styles.container}>
<FlatList
data={fruits}
renderItem={renderItems}
keyExtractor={(item) => item}
/>
</View>
);
}
function Screen2({ route }) {
const { item } = route.params;
return (
<View style={styles.container}>
<Text style={styles.text}>{item}</Text>
</View>
);
}
const Tab = createBottomTabNavigator();
export default function TabNavigator() {
return (
<NavigationContainer>
<Tab.Navigator>
<Tab.Screen
name="Screen1"
component={Screen1}
options={{
tabBarLabel: 'Screen 1',
}}
/>
<Tab.Screen
name="Screen2"
component={Screen2}
options={{
tabBarLabel: 'Screen 2',
}}
/>
</Tab.Navigator>
</NavigationContainer>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
paddingTop: Constants.statusBarHeight,
},
item_container: {
flexDirection: 'row',
margin: 5,
},
text: {
fontSize: 20,
margin: 5
}
});
不幸的是,由于您使用的是 React Native,它使用底层的本机 API 而您没有使用 Web 视图,因此您只能执行本机 iOS & Android 行为是。
在 Android 中,活动标签旁边的 2 个非活动标签(左侧和右侧)会在该活动标签打开时立即呈现。因此,当您点击下一个选项卡时,它实际上不需要做任何其他工作,从而可以快速加载。
因此您必须利用 state
管理库。每当有状态 属性 更新时,它都会强制重新呈现使用它的页面。因此,如果您在一个选项卡中分配一个新值,它应该会使用新值自动刷新任何相邻页面中的 UI。
谢谢大家的回答!事实上,Redux 是解决方案,我能够实现代码。
这是解决方案:)
import Constants from 'expo-constants';
import React, { useEffect } from 'react';
import { Text, View, FlatList, Button, StyleSheet } from 'react-native';
import { Provider, connect } from 'react-redux';
import { createStore, combineReducers } from 'redux';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import { NavigationContainer } from '@react-navigation/native';
const fruits = ['apples', 'watermelons', 'tomatoes', 'pomegranates', 'strawberries'];
function reducer(state, action) {
if (typeof state === 'undefined') {
return 'nothing!';
}
if (action.type === 'addItem') {
return action.value.item;
}
return state;
}
const store = createStore(combineReducers({ selectedItem: reducer }));
function Screen1({ selectedItem }) {
useEffect(() => {
console.log(store.getState());
}, [selectedItem]);
const renderItems = ({ item }) => {
return (
<View style={styles.item_container}>
<Text style={styles.text}>{item}</Text>
<Button
title="add"
onPress={() =>
store.dispatch({
type: 'addItem',
value: { item }
})
}
/>
</View>
);
};
return (
<View style={styles.container}>
<Text style={styles.title}>My favorite fruits:</Text>
<FlatList
data={fruits}
renderItem={renderItems}
keyExtractor={(item) => item}
/>
</View>
);
}
function Screen2({ selectedItem }) {
return (
<View style={styles.container}>
<Text style={styles.text}>You selected {selectedItem}</Text>
</View>
);
}
// Connect the screens to Redux
const Screen1Container = connect((state) => ({
selectedItem: state.selectedItem,
}))(Screen1);
const Screen2Container = connect((state) => ({
selectedItem: state.selectedItem,
}))(Screen2);
// Create the stack navigator
const Tab = createBottomTabNavigator();
export default function App() {
return (
<Provider store={store}>
<NavigationContainer>
<Tab.Navigator>
<Tab.Screen
name="Screen1"
component={Screen1Container}
options={{
tabBarLabel: 'Screen 1',
}}
/>
<Tab.Screen
name="Screen2"
component={Screen2Container}
options={{
tabBarLabel: 'Screen 2',
}}
/>
</Tab.Navigator>
</NavigationContainer>
</Provider>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
//justifyContent: 'center',
alignItems: 'center',
paddingTop: Constants.statusBarHeight,
},
title: {
fontSize: 25,
},
item_container: {
flexDirection: 'row',
marginVertical: 7,
},
text: {
fontSize: 20,
marginHorizontal: 7,
},
});
我有一个带有 2 个屏幕的底部选项卡导航器:Screen1 和 Screen2。
在 Screen1 中,有一个 FlatList 显示“水果”列表的内容: 它由一个项目和旁边的“添加”按钮组成。 当按下按钮时,该项目将显示在 Screen2 中。
我想在按下“添加”按钮时将 Screen1 中“水果”列表中的项目传递到 Screen2,而不自动路由到 Screen2。
到目前为止,我可以使用以下方法将项目从 Screen1 传递到 Screen2:navigation.navigate("Screen2", {item}),但它会自动将我带到 Screen2,这不是我想要的。
我觉得navigationprop的dispatch方法可以解决这个问题,但是不知道怎么用!
我正在使用 React Native 0.65 和 React Navigation 6.x。
调度方法的官方文档如下: https://reactnavigation.org/docs/navigation-prop/#dispatch
提前致谢。
这是我的代码:
import React from 'react';
import { Text, View, FlatList, Button, StyleSheet } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import Constants from 'expo-constants';
const fruits = [
'apples',
'watermelons',
'tomatoes',
'pomegranates',
'strawberries'
];
function Screen1({ navigation }) {
const renderItems = ({ item }) => {
return (
<View style={styles.item_container}>
<Text style={styles.text}>{item}</Text>
<Button
title="add"
onPress={() => navigation.navigate('Screen2', { item })}
/>
</View>
);
};
return (
<View style={styles.container}>
<FlatList
data={fruits}
renderItem={renderItems}
keyExtractor={(item) => item}
/>
</View>
);
}
function Screen2({ route }) {
const { item } = route.params;
return (
<View style={styles.container}>
<Text style={styles.text}>{item}</Text>
</View>
);
}
const Tab = createBottomTabNavigator();
export default function TabNavigator() {
return (
<NavigationContainer>
<Tab.Navigator>
<Tab.Screen
name="Screen1"
component={Screen1}
options={{
tabBarLabel: 'Screen 1',
}}
/>
<Tab.Screen
name="Screen2"
component={Screen2}
options={{
tabBarLabel: 'Screen 2',
}}
/>
</Tab.Navigator>
</NavigationContainer>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
paddingTop: Constants.statusBarHeight,
},
item_container: {
flexDirection: 'row',
margin: 5,
},
text: {
fontSize: 20,
margin: 5
}
});
不幸的是,由于您使用的是 React Native,它使用底层的本机 API 而您没有使用 Web 视图,因此您只能执行本机 iOS & Android 行为是。
在 Android 中,活动标签旁边的 2 个非活动标签(左侧和右侧)会在该活动标签打开时立即呈现。因此,当您点击下一个选项卡时,它实际上不需要做任何其他工作,从而可以快速加载。
因此您必须利用 state
管理库。每当有状态 属性 更新时,它都会强制重新呈现使用它的页面。因此,如果您在一个选项卡中分配一个新值,它应该会使用新值自动刷新任何相邻页面中的 UI。
谢谢大家的回答!事实上,Redux 是解决方案,我能够实现代码。
这是解决方案:)
import Constants from 'expo-constants';
import React, { useEffect } from 'react';
import { Text, View, FlatList, Button, StyleSheet } from 'react-native';
import { Provider, connect } from 'react-redux';
import { createStore, combineReducers } from 'redux';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import { NavigationContainer } from '@react-navigation/native';
const fruits = ['apples', 'watermelons', 'tomatoes', 'pomegranates', 'strawberries'];
function reducer(state, action) {
if (typeof state === 'undefined') {
return 'nothing!';
}
if (action.type === 'addItem') {
return action.value.item;
}
return state;
}
const store = createStore(combineReducers({ selectedItem: reducer }));
function Screen1({ selectedItem }) {
useEffect(() => {
console.log(store.getState());
}, [selectedItem]);
const renderItems = ({ item }) => {
return (
<View style={styles.item_container}>
<Text style={styles.text}>{item}</Text>
<Button
title="add"
onPress={() =>
store.dispatch({
type: 'addItem',
value: { item }
})
}
/>
</View>
);
};
return (
<View style={styles.container}>
<Text style={styles.title}>My favorite fruits:</Text>
<FlatList
data={fruits}
renderItem={renderItems}
keyExtractor={(item) => item}
/>
</View>
);
}
function Screen2({ selectedItem }) {
return (
<View style={styles.container}>
<Text style={styles.text}>You selected {selectedItem}</Text>
</View>
);
}
// Connect the screens to Redux
const Screen1Container = connect((state) => ({
selectedItem: state.selectedItem,
}))(Screen1);
const Screen2Container = connect((state) => ({
selectedItem: state.selectedItem,
}))(Screen2);
// Create the stack navigator
const Tab = createBottomTabNavigator();
export default function App() {
return (
<Provider store={store}>
<NavigationContainer>
<Tab.Navigator>
<Tab.Screen
name="Screen1"
component={Screen1Container}
options={{
tabBarLabel: 'Screen 1',
}}
/>
<Tab.Screen
name="Screen2"
component={Screen2Container}
options={{
tabBarLabel: 'Screen 2',
}}
/>
</Tab.Navigator>
</NavigationContainer>
</Provider>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
//justifyContent: 'center',
alignItems: 'center',
paddingTop: Constants.statusBarHeight,
},
title: {
fontSize: 25,
},
item_container: {
flexDirection: 'row',
marginVertical: 7,
},
text: {
fontSize: 20,
marginHorizontal: 7,
},
});