我几乎已经实现了这个滑块按钮来做我想要做的事情,但不幸的是,我注意到了一个小错误。为了提供上下文,我有一个主页,上面有一个滑块按钮。当我按下按钮时,它会呈现一个新屏幕。我还有一个名为Screen3的底部选项卡屏幕。目标是按下Screen3上的一个按钮,移动滑块按钮并渲染新屏幕。
我几乎已经成功地实现了这一点。当你第一眼进入Screen3并按下文本时,你可以看到它如我所希望的那样工作。然而,有一个小错误,如果你遵循这些步骤,你可以完全复制我所指的。
我已经提供了下面的一些代码,但这个小吃演示提供了你需要的一切。只要确保你在IOS或Android 中运行它
要重现错误,请执行以下操作
1.(单击底部选项卡栏中的Screen3,然后单击文本。它会把你带到";映射";屏幕以及更改滑块按钮。这正是我想要的
2.(现在单击滑块按钮,特别是"列表"。它会将屏幕更改回它最初是
3.(现在对于bug,如果你点击返回屏幕3,然后立即点击主页再次在底部的选项卡栏上,您可以看到我所指的bug。它将按钮更改为";映射";屏幕,即使它没有被渲染。
这是大部分代码,您可能可以在我提供的主页和滑块上进行调试。演示包含了其余的代码。
App.js
function MyTabs() {
return (
<Stack.Navigator
initialRouteName="Home">
<Stack.Screen name="Home" component= {Home} options={{headerShown: false}}/>
<Stack.Screen name="Screen1" component= {ListHome} options={{headerShown: false}}/>
<Stack.Screen name="Screen2" component= {MapHome} options={{headerShown: false}}/>
</Stack.Navigator>
);
}
export default function App() {
return (
<NavigationContainer>
<Tab.Navigator
initialRouteName="Home"
screenOptions={{
tabBarActiveTintColor: '#F60081',
tabBarInactiveTintColor: '#4d4d4d',
tabBarStyle: {
backgroundColor: '#d1cfcf',
borderTopColor: 'transparent',
},
}}
>
<Tab.Screen
name="Home"
component={MyTabs}
options={{
tabBarLabel: 'Home',
headerShown: false,
tabBarIcon: ({ color, size }) => (
<MaterialCommunityIcons name="home" color={color} size={size} />
),
}}
/>
<Tab.Screen
name="Screen3"
component={Screen3}
options={{
tabBarLabel: 'Screen3',
headerShown: false,
tabBarIcon: ({ color, size }) => (
<MaterialCommunityIcons name="account-group" color={color} size={size} />
),
}}
/>
</Tab.Navigator>
</NavigationContainer>
);
}
Home.js
const [isVisile, setIsVisible] = React.useState(true);
const [whichComponentToShow, setComponentToShow] = React.useState("Screen1");
React.useEffect(() => {
if(route.params && route.params?.componentToShow) {
setComponentToShow(route.params?.componentToShow);
goToMap()
}
}, [route.params]);
const goToMap = () => {
setComponentToShow("Screen2");
}
const goToList = () => {
setComponentToShow("Screen1");
}
return(
<View style={{backgroundColor: '#d1cfcf' ,flex: 1}}>
{whichComponentToShow === 'Screen1' && <ListHome />}
{whichComponentToShow === 'Screen2' && <MapHome />}
<View style={{position: 'absolute', top: 0, left: 0, right: 1}}>
<Top3
renderMap={goToMap}
renderList={goToList}
active={route.params && route.params?.componentToShow==='Screen2'|| false}
/>
</View>
</View>
);
}
export default Home;
slider.js 的顶部
const [active, setActive] = useState(false)
let transformX = useRef(new Animated.Value(0)).current;
useFocusEffect( React.useCallback(()=>{
setActive(Boolean(props.active))
console.log(props.active)
},[props.active]))
问题是screen.js
文件上的useFocuseEffect
...
useFocusEffect(
React.useCallback(() => {
setActive(Boolean(props.active));
console.log('focus effect running:', props.active);
}, [props.active])
);
...
每当screen.js
挂载时,就会调用此效果。
删除此项后,除单击Screen3文本时切换滑块外,其他一切都如预期一样工作。原因是只有在道具参数更改时才计算active
道具。为了解决这个问题,我们可以
将
active
的状态移动到负责检测参数变化的Home.js
。每当
params
发生变化时,设置值active
。使用此状态值而不是计算道具。
const Home = ({ route }) => {
const [isVisible, setIsVisible] = React.useState(true);
const [whichComponentToShow, setComponentToShow] = React.useState("Screen1");
const [active, setActive] = React.useState(false); // 1.
React.useEffect(() => {
if(route.params && route.params?.componentToShow) {
setComponentToShow(route.params?.componentToShow);
// 2.
if (route.params?.componentToShow === 'Screen2') {
setActive(true);
}
// goToMap()
}
}, [route.params]);
const goToMap = () => {
setActive(true);
setComponentToShow("Screen2");
}
const goToList = () => {
setActive(false);
setComponentToShow("Screen1");
}
return(
<View style={{backgroundColor: '#d1cfcf' ,flex: 1}}>
{whichComponentToShow === 'Screen1' && <ListHome />}
{whichComponentToShow === 'Screen2' && <MapHome />}
<View style={{position: 'absolute', top: 0, left: 0, right: 1}}>
<Top3
renderMap={goToMap}
renderList={goToList}
active={active}
/>
</View>
</View>
);
}
这是一份工作零食。https://snack.expo.dev/0DqR-KweY