Reputation: 33
So I am trying to adjust the position of a view. In doing so I have two components within a parent. One component is the navbar. It has buttons that change the content on the page. The other is the ContentBoard, this will display the different content. The ContentBoard also has a tab that needs to relocate to the correct button.
Where I'm stuck is that I have managed to get the navbar to change the tabID state in the parent, but then it should rerender the ContentBoard as it had the prop tabID. I'm just confused as to why when I send the state as a prop it is not automatically reloading the component since the value has changed.
Here is the code: Dashboard
const Dashboard = ({ navigation }) => {
const [email, setEmail] = useState("");
const [tabID, setTabID] = useState("2");
const user = auth.currentUser;
useEffect(() => {
if (user != null) {
user.providerData.forEach((userInfo) => {
setEmail(userInfo.email);
});
}
}, []);
function changeTab(id) {
setTabID(id);
}
return (
<KeyboardAwareScrollView
scrollEnabled={false}
behavior="padding"
contentContainerStyle={{ flex: 1 }}
>
<View style={{ flex: 1 }}>
<ImageBackground source={background} style={styles.backgroundImg}>
<ContentBoard activeBtn={tabID} />
<Navbar activeBtn={tabID} onPress={changeTab} />
</ImageBackground>
</View>
</KeyboardAwareScrollView>
);
};
Navbar
export default function Navbar(props) {
const activeBtnColor = "#53c5d6";
const regularBtnColor = "#00495f";
const activeBtn = props.activeBtn;
const styles = StyleSheet.create({
navbar: {
position: "absolute",
backgroundColor: "white",
opacity: 0.5,
width: "100%",
height: 100,
bottom: 0,
},
buttonContainer: {
flexDirection: "row",
width: "100%",
height: "100%",
justifyContent: "center",
alignItems: "center",
},
button: {
justifyContent: "center",
alignItems: "center",
borderRadius: 10,
width: 60,
height: 60,
margin: 5,
shadowColor: "black",
shadowRadius: 4,
shadowOpacity: 1,
shadowOffset: { width: 0, height: 4 },
elevation: 8,
},
familyTree: {
backgroundColor: `${activeBtn == 0 ? activeBtnColor : regularBtnColor}`,
},
calendar: {
backgroundColor: `${activeBtn == 1 ? activeBtnColor : regularBtnColor}`,
},
home: {
backgroundColor: `${activeBtn == 2 ? activeBtnColor : regularBtnColor}`,
},
memories: {
backgroundColor: `${activeBtn == 3 ? activeBtnColor : regularBtnColor}`,
},
notifications: {
backgroundColor: `${activeBtn == 4 ? activeBtnColor : regularBtnColor}`,
},
icon: {
width: 50,
height: 50,
},
});
return (
<View style={{ flex: 1 }}>
<View style={styles.navbar}>
<View style={styles.buttonContainer}>
<TouchableOpacity
style={[styles.familyTree, styles.button]}
onPress={() => props.onPress("0")}
>
<Image
style={styles.icon}
source={require("./../../assets/buttons/tree-icon.png")}
/>
</TouchableOpacity>
<TouchableOpacity
style={[styles.calendar, styles.button]}
onPress={() => props.onPress("1")}
>
<Image
style={styles.icon}
source={require("./../../assets/buttons/calendar-icon.png")}
/>
</TouchableOpacity>
<TouchableOpacity
style={[styles.home, styles.button]}
onPress={() => props.onPress("2")}
>
<Image
style={styles.icon}
source={require("./../../assets/buttons/home-icon.png")}
/>
</TouchableOpacity>
<TouchableOpacity
style={[styles.memories, styles.button]}
onPress={() => props.onPress("3")}
>
<Image
style={styles.icon}
source={require("./../../assets/buttons/folder-icon.png")}
/>
</TouchableOpacity>
<TouchableOpacity
style={[styles.notifications, styles.button]}
onPress={() => props.onPress("4")}
>
<Image
style={styles.icon}
source={require("./../../assets/buttons/bell-icon.png")}
/>
</TouchableOpacity>
</View>
</View>
</View>
);
}
ContentBoard
export default function ContentBoard(props) {
let tabOffset = 0;
let activeBtn = props.activeBtn;
useEffect(() => {
switch (activeBtn) {
case 0:
tabOffset = 140;
break;
case 1:
tabOffset = 70;
break;
case 2:
tabOffset = 0;
break;
case 3:
tabOffset = -70;
break;
case 4:
tabOffset = -140;
break;
}
}, [activeBtn]);
const styles = StyleSheet.create({
contentContainer: {
justifyContent: "center",
alignItems: "center",
backgroundColor: "white",
alignSelf: "center",
width: 350,
height: 650,
top: 40,
borderRadius: 20,
},
tab: {
position: "relative",
backgroundColor: "white",
alignSelf: "center",
borderRadius: 10,
right: tabOffset,
top: 12,
width: 70,
height: 135,
zIndex: -1,
},
});
return (
<View>
<View style={styles.contentContainer}></View>
<View style={[styles.tab]}></View>
</View>
);
I appreciate any help and would love to learn why this is not working, thanks.
Upvotes: 1
Views: 707
Reputation: 33
I worked it out. What I ended up doing was creating a hook in the primary to store the offset, pass the setOffset to the child component via a function. Have the offset changed in the child component, at the same time the offset is also passed by props to the child component to which it updates the style of the tab.
In short, I created a hook at the parent level that the child manipulates.
ContentBoard
const ContentBoard = (props) => {
useEffect(() => {
switch (props.activeBtn) {
case 0:
props.changeTabOffset(140);
break;
case 1:
props.changeTabOffset(70);
break;
case 2:
props.changeTabOffset(0);
break;
case 3:
props.changeTabOffset(-70);
break;
case 4:
props.changeTabOffset(-140);
break;
}
console.log("activeBtn: " + props.activeBtn);
}, [props.activeBtn]);
const styles = StyleSheet.create({
contentContainer: {
justifyContent: "center",
alignItems: "center",
backgroundColor: "white",
alignSelf: "center",
width: 350,
height: 650,
top: 40,
borderRadius: 20,
},
tab: {
position: "relative",
backgroundColor: "white",
alignSelf: "center",
borderRadius: 10,
right: props.offset,
top: 12,
width: 70,
height: 135,
zIndex: -1,
},
});
return (
<View>
<View style={styles.contentContainer}></View>
<View style={styles.tab}></View>
</View>
);
};
Dashboard
const Dashboard = ({ navigation }) => {
const [email, setEmail] = useState("");
const [tabID, setTabID] = useState(2);
const [tabOffset, setTabOffset] = useState(140);
const user = auth.currentUser;
useEffect(() => {
if (user != null) {
user.providerData.forEach((userInfo) => {
setEmail(userInfo.email);
});
}
}, []);
function changeTab(id) {
setTabID(id);
}
function changeTabOffset(offset) {
setTabOffset(offset);
}
return (
<KeyboardAwareScrollView
scrollEnabled={false}
behavior="padding"
contentContainerStyle={{ flex: 1 }}
>
<View style={{ flex: 1 }}>
<ImageBackground source={background} style={styles.backgroundImg}>
<ContentBoard
activeBtn={tabID}
offset={tabOffset}
changeTabOffset={changeTabOffset}
/>
<Navbar activeBtn={tabID} onPress={changeTab} />
</ImageBackground>
</View>
</KeyboardAwareScrollView>
);
};
const styles = StyleSheet.create({
backgroundImg: {
display: "flex",
flex: 1,
width: null,
height: null,
},
});
Upvotes: 1