refactor: fix context

This commit is contained in:
Jakub Grzywacz 2021-07-08 12:30:37 +02:00
parent e165a829b7
commit 4b72f5ec5b
No known key found for this signature in database
GPG Key ID: 5BBB685871FF63C4
5 changed files with 55 additions and 47 deletions

View File

@ -8,7 +8,6 @@ import {
Animated, Animated,
NativeSyntheticEvent, NativeSyntheticEvent,
NativeScrollEvent, NativeScrollEvent,
ViewToken,
} from 'react-native'; } from 'react-native';
import { CATEGORIES, CategoryTypes } from './types'; import { CATEGORIES, CategoryTypes } from './types';
import { EmojiCategory } from './components/EmojiCategory'; import { EmojiCategory } from './components/EmojiCategory';
@ -24,17 +23,6 @@ export const EmojiKeyboard = () => {
const scrollX = React.useRef(new Animated.Value(0)).current; const scrollX = React.useRef(new Animated.Value(0)).current;
const scrollNav = React.useRef(new Animated.Value(0)).current; const scrollNav = React.useRef(new Animated.Value(0)).current;
const onViewableItemsChanged = React.useRef(
({ viewableItems }: { viewableItems: Array<ViewToken> }) => {
if (viewableItems.length > 0 && viewableItems[0].index !== null) {
ctx?.setActiveCategoryIndex(viewableItems[0].index);
}
}
);
const viewabilityConfig = React.useRef({
viewAreaCoveragePercentThreshold: 60,
});
const getItemLayout = ( const getItemLayout = (
_: CategoryTypes[] | null | undefined, _: CategoryTypes[] | null | undefined,
index: number index: number
@ -66,7 +54,7 @@ export const EmojiKeyboard = () => {
); );
return ( return (
<View style={[styles.container, ctx?.containerStyles]}> <View style={[styles.container, ctx.containerStyles]}>
<FlatList <FlatList
data={CATEGORIES} data={CATEGORIES}
keyExtractor={(item) => item} keyExtractor={(item) => item}
@ -81,8 +69,6 @@ export const EmojiKeyboard = () => {
decelerationRate="fast" decelerationRate="fast"
getItemLayout={getItemLayout} getItemLayout={getItemLayout}
onScroll={onScroll} onScroll={onScroll}
onViewableItemsChanged={onViewableItemsChanged.current}
viewabilityConfig={viewabilityConfig.current}
/> />
<Categories flatListRef={flatListRef} scrollNav={scrollNav} /> <Categories flatListRef={flatListRef} scrollNav={scrollNav} />
</View> </View>

View File

@ -1,18 +1,25 @@
import * as React from 'react'; import * as React from 'react';
import type { ViewStyle } from 'react-native'; import type { ViewStyle } from 'react-native';
import {
defaultKeyboardContext,
defaultKeyboardValues,
} from './KeyboardProvider';
import type { EmojiType } from './types'; import type { EmojiType } from './types';
export type KeyboardProps = { export type KeyboardProps = {
onEmojiSelected: (emoji: EmojiType) => void; onEmojiSelected: (emoji: EmojiType) => void;
numberOfColumns?: number;
emojiSize?: number; emojiSize?: number;
containerStyles?: ViewStyle; containerStyles?: ViewStyle;
}; };
export type ContextValues = { export type ContextValues = {
activeCategoryIndex: number; activeCategoryIndex: number;
setActiveCategoryIndex: (index: number) => void; setActiveCategoryIndex: (index: number) => void;
numberOfColumns: number;
}; };
export const KeyboardContext = React.createContext< export const KeyboardContext = React.createContext<
(KeyboardProps & ContextValues) | null Required<KeyboardProps> & ContextValues
>(null); >({
...defaultKeyboardContext,
...defaultKeyboardValues,
});

View File

@ -10,20 +10,26 @@ type ProviderProps = KeyboardProps & {
children: React.ReactNode; children: React.ReactNode;
}; };
export const defaultKeyboardContext: KeyboardProps = { export const defaultKeyboardContext: Required<KeyboardProps> = {
onEmojiSelected: (_emoji: EmojiType) => {}, onEmojiSelected: (_emoji: EmojiType) => {},
numberOfColumns: 7,
emojiSize: 24, emojiSize: 24,
containerStyles: {},
}; };
export const defaultKeyboardValues: Partial<ContextValues> = { export const defaultKeyboardValues: ContextValues = {
// activeCategoryIndex: 0, activeCategoryIndex: 0,
setActiveCategoryIndex: () => {},
numberOfColumns: 5,
}; };
export const KeyboardProvider: React.FC<ProviderProps> = React.memo((props) => { export const KeyboardProvider: React.FC<ProviderProps> = React.memo((props) => {
const [activeCategoryIndex, setActiveCategoryIndex] = React.useState(0); const [activeCategoryIndex, setActive] = React.useState(0);
const value: KeyboardProps & ContextValues = { const setActiveCategoryIndex = React.useCallback((index: number) => {
setActive(index);
}, []);
const value: Required<KeyboardProps> & ContextValues = {
...defaultKeyboardContext, ...defaultKeyboardContext,
...defaultKeyboardValues, ...defaultKeyboardValues,
...props, ...props,

View File

@ -11,35 +11,45 @@ type CategoriesProps = {
export const Categories = ({ flatListRef, scrollNav }: CategoriesProps) => { export const Categories = ({ flatListRef, scrollNav }: CategoriesProps) => {
const ctx = React.useContext(KeyboardContext); const ctx = React.useContext(KeyboardContext);
const handleScrollToCategory = (category: CategoryTypes) => { const handleScrollToCategory = React.useCallback(
(category: CategoryTypes) => {
flatListRef?.current?.scrollToIndex({ flatListRef?.current?.scrollToIndex({
index: CATEGORIES.indexOf(category), index: CATEGORIES.indexOf(category),
}); });
}; },
[flatListRef]
);
const rendarItem = React.useCallback(
({ item, index }) => (
<CategoryItem
item={item}
index={index}
handleScrollToCategory={handleScrollToCategory}
/>
),
[handleScrollToCategory]
);
const activeIndicator = React.useCallback(
() => (
<Animated.View style={[styles.activeIndicator, { left: scrollNav }]} />
),
[scrollNav]
);
return ( return (
<View style={styles.bottomBar}> <View style={styles.bottomBar}>
<View style={styles.navigation}> <View style={styles.navigation}>
<FlatList <FlatList
data={CATEGORIES_NAVIGATION} data={CATEGORIES_NAVIGATION}
keyExtractor={(item) => item.category} keyExtractor={(item) => item.category}
renderItem={({ item, index }) => ( renderItem={rendarItem}
<CategoryItem
item={item}
index={index}
handleScrollToCategory={handleScrollToCategory}
/>
)}
ItemSeparatorComponent={() => <View style={styles.separator} />} ItemSeparatorComponent={() => <View style={styles.separator} />}
scrollEnabled={false} scrollEnabled={false}
horizontal={true} horizontal={true}
onScrollToIndexFailed={(e) => console.log(e)} onScrollToIndexFailed={(e) => console.log(e)}
ListHeaderComponent={() => { ListHeaderComponent={activeIndicator}
return (
<Animated.View
style={[styles.activeIndicator, { left: scrollNav }]}
/>
);
}}
extraData={ctx?.activeCategoryIndex} extraData={ctx?.activeCategoryIndex}
/> />
</View> </View>

View File

@ -16,10 +16,9 @@ export const EmojiCategory = ({ item }: { item: CategoryTypes }) => {
const { width } = useWindowDimensions(); const { width } = useWindowDimensions();
const ctx = React.useContext(KeyboardContext); const ctx = React.useContext(KeyboardContext);
const numberOfColumns = React.useRef<number>( const numberOfColumns = React.useRef<number>(
Math.floor(width / (ctx?.emojiSize ? ctx?.emojiSize : 0 + 16)) Math.floor(width / (ctx.emojiSize + 16))
); );
const [data, setData] = React.useState<EmojiType[]>([]); const [data, setData] = React.useState<EmojiType[]>([]);
// console.log(width);
React.useEffect(() => { React.useEffect(() => {
const newData = emojisByGroup[item]; const newData = emojisByGroup[item];
@ -63,11 +62,11 @@ const styles = StyleSheet.create({
container: { container: {
flex: 1, flex: 1,
paddingHorizontal: 10, paddingHorizontal: 10,
marginTop: 12, marginTop: 6,
}, },
sectionTitle: { sectionTitle: {
opacity: 0.6, opacity: 0.6,
marginBottom: 12, marginBottom: 6,
marginLeft: 12, marginLeft: 12,
}, },
footer: { height: 70 }, footer: { height: 70 },