Я использую реагирующий на родство с реагирующей навигацией
Я создал 2 createAppContainer, один для всего приложения и еще один для BottomNavigation, контекст работал отлично, но реакция-навигация вызывает ошибку, потому что я Я использую 2 AppContainerStacks отдельно, я попытался изменить компонент Home, чтобы устранить эту проблему, и проблема с реакцией навигации исчезла, но контекст больше не работает, и я не могу получить данные, поступающие оттуда.
Все, что я сделал, это просто извлек данные из <HomeBottomTabNavigator />
снаружи в том же месте.
Я использовал их таким образом
Домой. js
/** @flow **/
import React, { useEffect, useState } from 'react';
import type { ViewStyleProp } from 'react-native/Libraries/StyleSheet/StyleSheet';
import { useMutation } from '@apollo/react-hooks';
import { GET_USER_DATA } from '../actions/mutations';
import { UserProvider } from '../core/context/userContext';
import { ResponseUtil } from '../core/utils/responseUtils';
import { Layout, withStyles } from '@ui-kitten/components';
import { getAccessToken } from '../core/utils/asyncStorageUtils';
import { HomeBottomTabNavigator } from '../core/navigations/tabNavigator';
type HomeScreenPropsType = {
themedStyle: {
container: ViewStyleProp
}
};
function HomeScreen(props: HomeScreenPropsType): React$Element<any> {
const { themedStyle } = props;
const [userData, setUserData] = useState({});
const [getUserData] = useMutation(GET_USER_DATA);
useEffect(() => {
const fetchUserData = async () => {
const accessToken = await getAccessToken();
const mutationVariables = { input: { provider: 'facebook', accessToken: accessToken } };
const response = await getUserData({ variables: mutationVariables });
const tidyData = ResponseUtil.socialAuthResponseFormatter(response);
setUserData(tidyData);
};
fetchUserData();
}, [getUserData]);
return (
<Layout testID={'home-screen'} style={themedStyle.container}>
<UserProvider value={userData}>
<HomeBottomTabNavigator />
</UserProvider>
</Layout>
);
}
export const Home: React$StatelessFunctionalComponent<any> = withStyles(HomeScreen, () => ({
container: {
flex: 1
}
}));
tabNavigator. js
/** @flow **/
import React from 'react';
import type { NavigationContainer } from 'react-navigation';
import { createBottomTabNavigator } from 'react-navigation-tabs';
import { createAppContainer, SafeAreaView } from 'react-navigation';
import { BottomNavigation, BottomNavigationTab, Icon } from '@ui-kitten/components';
import { SCREENS } from './screens';
import { Friends } from '../../screens/Friends';
import { Messages } from '../../screens/Messages';
import { Settings } from '../../screens/Settings';
const TabBarComponent = ({ navigation }): React$Element<any> => {
const onSelect = (index) => {
const selectedTabRoute = navigation.state.routes[index];
navigation.navigate(selectedTabRoute.routeName);
};
const bottomTabIcon = (style, iconName): React$Element<Icon> => <Icon {...style} name={iconName} />;
return (
<SafeAreaView>
<BottomNavigation selectedIndex={navigation.state.index} onSelect={onSelect}>
<BottomNavigationTab title={SCREENS.MESSAGES} icon={(style) => bottomTabIcon(style, 'email-outline')} />
<BottomNavigationTab title={SCREENS.FRIENDS} icon={(style) => bottomTabIcon(style, 'person-outline')} />
<BottomNavigationTab title={SCREENS.SETTINGS} icon={(style) => bottomTabIcon(style, 'options-2-outline')} />
</BottomNavigation>
</SafeAreaView>
);
};
const TabNavigator = createBottomTabNavigator(
{
[SCREENS.MESSAGES]: Messages,
[SCREENS.FRIENDS]: Friends,
[SCREENS.SETTINGS]: Settings
},
{
tabBarComponent: TabBarComponent
}
);
export const HomeBottomTabNavigator: NavigationContainer = createAppContainer(TabNavigator);
контекст работал отлично, но реакция-навигация вызывает ошибку, потому что я использую 2 AppContainerStacks отдельно, я пытался изменить компонент Home, чтобы устранить эту проблему, например следующая
Home. js
/** @flow **/
import { UserProvider } from '../core/context/userContext';
import { useMutation } from '@apollo/react-hooks';
import React, { useEffect, useState } from 'react';
import type { NavigationContainer } from 'react-navigation';
import { createBottomTabNavigator } from 'react-navigation-tabs';
import { createAppContainer, SafeAreaView } from 'react-navigation';
import type { ViewStyleProp } from 'react-native/Libraries/StyleSheet/StyleSheet';
import { BottomNavigation, BottomNavigationTab, Icon, Layout } from '@ui-kitten/components';
import { Messages } from './Messages';
import { Friends } from './Friends';
import { Settings } from './Settings';
import { GET_USER_DATA } from '../actions/mutations';
import { SCREENS } from '../core/navigations/screens';
import { ResponseUtil } from '../core/utils/responseUtils';
import { getAccessToken } from '../core/utils/asyncStorageUtils';
type HomeScreenPropsType = {
themedStyle: {
container: ViewStyleProp
}
};
function HomeScreen(props: HomeScreenPropsType): React$Element<any> {
const { navigation } = props;
const [userData, setUserData] = useState({});
const [getUserData] = useMutation(GET_USER_DATA);
useEffect(() => {
const fetchUserData = async () => {
const accessToken = await getAccessToken();
const mutationVariables = { input: { provider: 'facebook', accessToken: accessToken } };
const response = await getUserData({ variables: mutationVariables });
const tidyData = ResponseUtil.socialAuthResponseFormatter(response);
setUserData(tidyData);
};
fetchUserData();
}, [getUserData]);
const onSelect = (index) => {
const selectedTabRoute = navigation.state.routes[index];
navigation.navigate(selectedTabRoute.routeName);
};
const bottomTabIcon = (style, iconName): React$Element<Icon> => <Icon {...style} name={iconName} />;
return (
<Layout testID={'home-screen'}>
<UserProvider value={userData}>
<SafeAreaView>
<BottomNavigation selectedIndex={navigation.state.index} onSelect={onSelect}>
<BottomNavigationTab title={SCREENS.MESSAGES} icon={(style) => bottomTabIcon(style, 'email-outline')} />
<BottomNavigationTab title={SCREENS.FRIENDS} icon={(style) => bottomTabIcon(style, 'person-outline')} />
<BottomNavigationTab title={SCREENS.SETTINGS} icon={(style) => bottomTabIcon(style, 'options-2-outline')} />
</BottomNavigation>
</SafeAreaView>
</UserProvider>
</Layout>
);
}
const TabNavigator = createBottomTabNavigator(
{
[SCREENS.MESSAGES]: Messages,
[SCREENS.FRIENDS]: Friends,
[SCREENS.SETTINGS]: Settings
},
{
tabBarComponent: HomeScreen
}
);
export const Home: NavigationContainer = createAppContainer(TabNavigator);
и проблема реагирования-навигации исчезла, но контекст больше не работает, и я не могу получить данные, поступающие оттуда.
вот как я использовал контекст
Friends. js
/** @flow **/
import React from 'react';
import { SafeAreaView } from 'react-navigation';
import { Image, StyleSheet } from 'react-native';
import { Layout, List, ListItem, withStyles } from '@ui-kitten/components';
import type { ViewStyleProp } from 'react-native/Libraries/StyleSheet/StyleSheet';
import { useUserContext } from '../core/context/userContext';
type FriendsScreenPropsType = {
themedStyle: {
container: ViewStyleProp,
safeAreaViewContainer: ViewStyleProp,
list: ViewStyleProp,
contentContainer: ViewStyleProp,
listItem: ViewStyleProp
}
};
export const FriendsScreen = (props: FriendsScreenPropsType): React$Element<any> => {
const { themedStyle } = props;
const user = useUserContext();
const renderProfilePicture = (picture, style): React$Element<Image> => (
<Image style={style} source={{ uri: picture }} />
);
const renderItem = ({ item }): React$Element<ListItem> => {
const iconStyle = StyleSheet.create({ width: 50, height: 50, borderRadius: 50 });
return (
<ListItem
style={themedStyle.listItem}
title={item.name}
icon={(): React$Element<Image> => renderProfilePicture(item.picture, iconStyle)}
/>
);
};
return (
<Layout level='3' style={themedStyle.container}>
<SafeAreaView style={themedStyle.safeAreaViewContainer}>
<List
data={user.friends}
renderItem={renderItem}
contentContainerStyle={themedStyle.contentContainer}
style={themedStyle.list}
/>
</SafeAreaView>
</Layout>
);
};
export const Friends: React$StatelessFunctionalComponent<any> = withStyles(FriendsScreen, () => ({
container: {
flex: 1
},
safeAreaViewContainer: {
flex: 1
},
list: {
backgroundColor: 'transparent'
},
contentContainer: {
paddingVertical: 1
},
listItem: {
marginVertical: 2
}
}));
и это файл контекста я сделал -> userContext. js
/** @flow **/
import React, { createContext, useContext } from 'react';
const UserContext = createContext({});
export function useUserContext(): any {
return useContext(UserContext);
}
type ThemeProviderPropsType = {
children: React$Node,
value: any
};
export function UserProvider(props: ThemeProviderPropsType): React$Node {
const { children, value } = props;
return <UserContext.Provider value={value}>{children}</UserContext.Provider>;
}