React 本机导航 - Material 顶部选项卡在状态更改时不重新呈现
React native navigation - Material top tabs not re-rendering when state changes
我对 material 顶部标签有一个奇怪的问题。我正在尝试获取数据,然后在选项卡中显示该数据。但是,即使useQuery数据发生变化,也不会触发重新渲染。
Navigation.tsx
const CulturalHeritageTab =
createMaterialTopTabNavigator<CulturalHeritageTabParamList>();
export const CulturalHeritageTabNavigator = () => {
return (
<CulturalHeritageTab.Navigator>
<CulturalHeritageTab.Group
screenOptions={{
swipeEnabled: false,
tabBarItemStyle: { ...styles.tab },
tabBarLabelStyle: { ...fonts.topButton },
}}>
<CulturalHeritageTab.Screen
name="Tour"
children={CulturalHeritageList}
/>
<CulturalHeritageTab.Screen
name="Exibition"
children={CulturalHeritageList}
/>
</CulturalHeritageTab.Group>
</CulturalHeritageTab.Navigator>
);
};
Page.tsx
export const CulturalHeritageList = () => {
const navigation = useNavigation<CulturalHeritageNavigationProp>();
const { t, i18n } = useTranslation();
const { data, error, loading } = useQuery< //<--- This should rerender
ICulturalHeritageListData,
ICulturalHeritageListVars
>(ALL_CULTURAL_HERITAGE_LIST, {
variables: {
filter: {
where: {
expired: null,
},
},
lang: i18n.language,
},
});
const renderItem = (
{ item, index }: { item: ICulturalHeritageList; index: number },
parallaxProps: AdditionalParallaxProps | undefined,
) => {
const source = { uri: `${API_BUCKET}${item.media.path}` };
const navigateToDetails = () => {
navigation.navigate('CulturalHeritageDetails', { item: item });
};
return (
<View style={styles.item} key={index}>
<ParallaxImage
source={source}
containerStyle={styles.imageContainer}
style={styles.image}
parallaxFactor={0.4}
{...parallaxProps}
/>
<View style={styles.textContainer}>
<Text style={[fonts.cardTitle]}>
{item.culturalHeritageLocale[0].title}
</Text>
<View style={global.divider} />
<Button light width="sm" onPress={navigateToDetails}>
See More
</Button>
<Text style={styles.time}>
<Icon name="time-outline" style={styles.icon} />
{item.duration
? `${
Math.floor(item.duration / 60)
? Math.floor(item.duration / 60) + 'h '
: ''
}${item.duration % 60 ? (item.duration % 60) + 'm' : ''}`
: '- No duration -'}
</Text>
</View>
</View>
);
};
if (error) {
console.log(JSON.stringify(error, null, 2));
}
if (data) {
console.log('CulturalHeritageList: ', data);
}
console.log(loading);
return (
<View style={global.container}>
<ImageBackground source={image} resizeMode="cover" style={styles.image}>
{loading ? (
<ActivityIndicator size="large" />
) : error ? (
<Text>{t('Error')}</Text>
) : data?.culturalHeritages.length ? (
<Carousel
data={data.culturalHeritages}
containerCustomStyle={styles.carousel}
// @ts-ignore
renderItem={renderItem}
sliderWidth={width}
sliderHeight={height * 0.5}
itemWidth={width * 0.5}
itemHeight={height * 0.5}
hasParallaxImages={true}
/>
) : (
<Text>{t('NoDataFound')}</Text>
)}
</ImageBackground>
</View>
);
};
加载和数据更新时,屏幕卡在 ActivityIndicator 组件上,但没有触发重新渲染。它只发生在 Material 顶部选项卡内。如何在加载或数据更改时重新呈现此选项卡?
更新:弹出此错误:
Warning: React has detected a change in the order of Hooks called by SceneView. This will lead to bugs and errors if not fixed. For more information, read the Rules of Hooks
1. useRef useRef
2. useCallback useCallback
3. useRef useRef
4. useRef useRef
5. useContext useContext
6. useContext useContext
7. useCallback useCallback
8. useEffect useEffect
9. useCallback useCallback
10. useCallback useCallback
11. useEffect useEffect
12. useCallback useCallback
13. useCallback useCallback
14. useCallback useCallback
15. useCallback useCallback
16. useRef useRef
17. useEffect useEffect
18. useEffect useEffect
19. useCallback useCallback
20. useMemo useMemo
21. useContext useContext
22. useState useContext
我不得不使用组件而不是子组件:
<CulturalHeritageTab.Screen
name="Exibition"
component={CulturalHeritageList}
/>
我对 material 顶部标签有一个奇怪的问题。我正在尝试获取数据,然后在选项卡中显示该数据。但是,即使useQuery数据发生变化,也不会触发重新渲染。
Navigation.tsx
const CulturalHeritageTab =
createMaterialTopTabNavigator<CulturalHeritageTabParamList>();
export const CulturalHeritageTabNavigator = () => {
return (
<CulturalHeritageTab.Navigator>
<CulturalHeritageTab.Group
screenOptions={{
swipeEnabled: false,
tabBarItemStyle: { ...styles.tab },
tabBarLabelStyle: { ...fonts.topButton },
}}>
<CulturalHeritageTab.Screen
name="Tour"
children={CulturalHeritageList}
/>
<CulturalHeritageTab.Screen
name="Exibition"
children={CulturalHeritageList}
/>
</CulturalHeritageTab.Group>
</CulturalHeritageTab.Navigator>
);
};
Page.tsx
export const CulturalHeritageList = () => {
const navigation = useNavigation<CulturalHeritageNavigationProp>();
const { t, i18n } = useTranslation();
const { data, error, loading } = useQuery< //<--- This should rerender
ICulturalHeritageListData,
ICulturalHeritageListVars
>(ALL_CULTURAL_HERITAGE_LIST, {
variables: {
filter: {
where: {
expired: null,
},
},
lang: i18n.language,
},
});
const renderItem = (
{ item, index }: { item: ICulturalHeritageList; index: number },
parallaxProps: AdditionalParallaxProps | undefined,
) => {
const source = { uri: `${API_BUCKET}${item.media.path}` };
const navigateToDetails = () => {
navigation.navigate('CulturalHeritageDetails', { item: item });
};
return (
<View style={styles.item} key={index}>
<ParallaxImage
source={source}
containerStyle={styles.imageContainer}
style={styles.image}
parallaxFactor={0.4}
{...parallaxProps}
/>
<View style={styles.textContainer}>
<Text style={[fonts.cardTitle]}>
{item.culturalHeritageLocale[0].title}
</Text>
<View style={global.divider} />
<Button light width="sm" onPress={navigateToDetails}>
See More
</Button>
<Text style={styles.time}>
<Icon name="time-outline" style={styles.icon} />
{item.duration
? `${
Math.floor(item.duration / 60)
? Math.floor(item.duration / 60) + 'h '
: ''
}${item.duration % 60 ? (item.duration % 60) + 'm' : ''}`
: '- No duration -'}
</Text>
</View>
</View>
);
};
if (error) {
console.log(JSON.stringify(error, null, 2));
}
if (data) {
console.log('CulturalHeritageList: ', data);
}
console.log(loading);
return (
<View style={global.container}>
<ImageBackground source={image} resizeMode="cover" style={styles.image}>
{loading ? (
<ActivityIndicator size="large" />
) : error ? (
<Text>{t('Error')}</Text>
) : data?.culturalHeritages.length ? (
<Carousel
data={data.culturalHeritages}
containerCustomStyle={styles.carousel}
// @ts-ignore
renderItem={renderItem}
sliderWidth={width}
sliderHeight={height * 0.5}
itemWidth={width * 0.5}
itemHeight={height * 0.5}
hasParallaxImages={true}
/>
) : (
<Text>{t('NoDataFound')}</Text>
)}
</ImageBackground>
</View>
);
};
加载和数据更新时,屏幕卡在 ActivityIndicator 组件上,但没有触发重新渲染。它只发生在 Material 顶部选项卡内。如何在加载或数据更改时重新呈现此选项卡?
更新:弹出此错误:
Warning: React has detected a change in the order of Hooks called by SceneView. This will lead to bugs and errors if not fixed. For more information, read the Rules of Hooks
1. useRef useRef
2. useCallback useCallback
3. useRef useRef
4. useRef useRef
5. useContext useContext
6. useContext useContext
7. useCallback useCallback
8. useEffect useEffect
9. useCallback useCallback
10. useCallback useCallback
11. useEffect useEffect
12. useCallback useCallback
13. useCallback useCallback
14. useCallback useCallback
15. useCallback useCallback
16. useRef useRef
17. useEffect useEffect
18. useEffect useEffect
19. useCallback useCallback
20. useMemo useMemo
21. useContext useContext
22. useState useContext
我不得不使用组件而不是子组件:
<CulturalHeritageTab.Screen
name="Exibition"
component={CulturalHeritageList}
/>