我是React Native的新手,我正在努力让一个子视图在应该更新/重新渲染的时候更新/重新渲染。代码粘贴在下面。UserProfile包含一个带有Posts,Diet,Workouts和Gallery的标签栏。UserProfileGalleryView包含一个图像网格。单击图像时,应该打开一个显示图像的模态视图,但目前它只会在我单击图像时显示,点击posts/diet/workout,然后点击返回到画廊。一旦我点击返回到画廊,模态视图显示,关闭按钮并没有关闭它。很明显,我的状态没有得到正确的管理。我已经尝试使用useEffect和useContext无效。任何帮助都将不胜感激。
UserProfile(父组件):
import { Auth } from "aws-amplify";
import React, { useEffect } from "react";
import {
View,
SafeAreaView,
Text,
StyleSheet,
Pressable,
Image,
TurboModuleRegistry,
} from "react-native";
import UserProfileWorkoutsView from "./UserProfileWorkoutsView";
import UserProfileDietView from "./UserProfileDietView";
import UserProfileGalleryView from "./UserProfileGalleryView";
import UserProfilePostsView from "./UserProfilePostsView";
function UserProfile({ route, navigation }) {
const [currentView, setCurrentView] = React.useState(UserProfilePostsView);
const userInfo = route.params.userInfo;
const onSettingsPressed = async (data) => {
navigation.navigate("Settings");
};
const [modalVisible, setModalVisible] = React.useState(false);
const [selectedImage, setSelectedImage] = React.useState(null);
const toggleModalView = () => {
setModalVisible(!modalVisible);
};
const updateSelectedImage = (item) => {
setSelectedImage(item);
};
const onPress = (data) => {
switch (data["_targetInst"]["alternate"]["memoizedProps"]["name"]) {
case "postsButton":
setCurrentView(UserProfilePostsView);
return;
case "workoutsButton":
setCurrentView(UserProfileWorkoutsView);
return;
case "dietButton":
setCurrentView(UserProfileDietView);
return;
case "galleryButton":
setCurrentView(() => (
<UserProfileGalleryView
toggleModalView={toggleModalView}
updateSelectedImage={updateSelectedImage}
modalVisible={modalVisible}
selectedImage={selectedImage}
/>
));
return;
}
};
return (
<SafeAreaView
style={styles.container}
contentInsetAdjustmentBehavior="never"
>
<View style={styles.profileHeader}>
<Pressable style={styles.profilePic} onPress={() => {}}>
<Image
style={{ width: 100, height: 100, resizeMode: "contain" }}
source={require("./assets/profile_pic_temp.png")}
/>
</Pressable>
<View>
<Text style={{ fontWeight: "bold" }}>
STREAK {userInfo.userStreak} 🔥
</Text>
<Text style={{ fontWeight: "bold", fontSize: 24 }}>
{userInfo.userFirstLastName}
</Text>
<Text style={{}}>{userInfo.userBio}</Text>
</View>
</View>
<View style={styles.tabBar}>
<Pressable
style={styles.tabBarIcon}
name="postsButton"
onPress={onPress}
>
<Image
style={styles.tabBarIcon}
source={require("./assets/posts_icon.png")}
/>
</Pressable>
<Pressable
style={styles.tabBarIcon}
name="workoutsButton"
onPress={onPress}
>
<Image
style={styles.tabBarIcon}
source={require("./assets/barbell-hand.png")}
/>
</Pressable>
<Pressable
style={styles.tabBarIcon}
name="dietButton"
onPress={onPress}
>
<Image
style={styles.tabBarIcon}
source={require("./assets/diet_icon.png")}
/>
</Pressable>
<Pressable
style={styles.tabBarIcon}
name="galleryButton"
onPress={onPress}
>
<Image
style={styles.tabBarIcon}
source={require("./assets/gallery_icon.png")}
/>
</Pressable>
</View>
<Pressable style={styles.settingsButton} onPress={onSettingsPressed}>
<Image
style={{ width: 40, height: 40, resizeMode: "contain" }}
source={require("./assets/settings_cog.png")}
/>
</Pressable>
<View style={styles.contentContainer}>{currentView}</View>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "dodgerblue",
alignItems: "center",
justifyContent: "flex-start",
},
settingsButton: {
position: "absolute",
alignSelf: "flex-end",
height: 40,
width: 40,
marginTop: 60,
paddingRight: 60,
},
profileHeader: {
alignItems: "flex-start",
flexDirection: "row",
marginTop: 20,
width: "100%",
marginHorizontal: 80,
},
profilePic: {
alignSelf: "flex-start",
marginRight: 10,
marginLeft: 10,
},
tabBar: {
height: 40,
flexDirection: "row",
justifyContent: "space-between",
width: "100%",
backgroundColor: "lightblue",
alignItems: "center",
marginTop: 20,
},
tabBarIcon: {
flex: 1,
alignSelf: "center",
width: 30,
height: 30,
resizeMode: "contain",
},
contentContainer: {
flex: 1,
width: "100%",
//backgroundColor: "white",
},
});
export default UserProfile;
UserProfileGalleryView(子组件):
import React, { useEffect } from "react";
import {
StyleSheet,
Image,
FlatList,
Dimensions,
Modal,
TouchableOpacity,
View,
} from "react-native";
//temp for displaying purposes
const userImages = new Array(17).fill("https://picsum.photos/400");
const screenWidth = Dimensions.get("window").width;
const numColumns = 3;
const tileSize = screenWidth / numColumns;
function renderItem({ item, props }) {
//Single item of Grid
return (
<TouchableOpacity
key={item.id}
style={{ height: tileSize, width: tileSize }}
onPress={() => {
props.toggleModalView();
props.updateSelectedImage(item);
}}
>
<Image resizeMode="cover" style={{ flex: 1 }} source={{ uri: item }} />
</TouchableOpacity>
);
}
function UserProfileGalleryView(props) {
if (props.modalVisible) {
//Modal to show full image with close button
return (
<Modal
transparent={false}
animationType={"fade"}
visible={props.modalVisible}
onRequestClose={() => {
props.toggleModalView();
}}
>
<View style={styles.modelStyle}>
<Image
style={styles.fullImageStyle}
source={{ uri: props.selectedImage }}
/>
<TouchableOpacity
activeOpacity={0.5}
style={styles.closeButtonStyle}
onPress={() => {
props.toggleModalView();
}}
>
<Image
source={{
uri: "https://cdn2.iconfinder.com/data/icons/media-controls-5/100/close-1024.png",
}}
style={{ width: 25, height: 25, marginTop: 16 }}
/>
</TouchableOpacity>
</View>
</Modal>
);
} else {
return (
<FlatList
data={userImages}
renderItem={({ item }) =>
renderItem({
item,
props,
})
}
numColumns={3}
/>
);
}
}
const styles = StyleSheet.create({
photoGrid: {
flex: 3,
marginHorizontal: "auto",
backgroundColor: "dodgerblue",
},
row: {
flexDirection: "row",
},
col: {
backgroundColor: "dodgerblue",
borderColor: "#fff",
borderWidth: 1,
flex: 3,
},
galleryImage: {
width: "100%",
resizeMode: "contain",
},
containerStyle: {
justifyContent: "center",
flex: 1,
marginTop: 20,
},
fullImageStyle: {
justifyContent: "center",
alignItems: "center",
height: "100%",
width: "98%",
resizeMode: "contain",
},
modelStyle: {
flex: 1,
justifyContent: "center",
alignItems: "center",
backgroundColor: "rgba(0,0,0,0.4)",
},
closeButtonStyle: {
width: 25,
height: 25,
top: 50,
right: 20,
position: "absolute",
},
});
export default UserProfileGalleryView;
2条答案
按热度按时间3pmvbmvn1#
为我的评论提供适当的答案/解释。
您可以使用
onPress
函数为currentView
设置一个字符串,并根据该状态渲染组件。bttbmeg02#
我同意上面的评论,不建议将组件存储在状态中。
也就是说,我相信你遇到的问题是在你的onPress事件中,当你设置当前视图时,你没有为你的gallery模态翻转模态状态。所以视图被设置了,但是
modalVisible = false
的状态值被传递给你的子组件,模态没有显示。我想这会解决你的问题:
添加
setModalVisible(true)
这一行应该会在你第一次设置视图时显示模态,但允许你像当前的设置一样隐藏它。