Skip to content

t1k:rn:base:components

FieldValue
Modulebase
Version1.7.4
Effortmedium
Tools

Keywords: components, core components, FlatList, hooks, memo, react native

/t1k:rn:base:components

// Typed component with forwarded ref
import { View, StyleSheet, ViewProps } from 'react-native';
interface CardProps extends ViewProps {
title: string;
onPress?: () => void;
}
export const Card = memo(({ title, onPress, style, ...props }: CardProps) => (
<Pressable onPress={onPress} style={[styles.card, style]} {...props}>
<Text style={styles.title}>{title}</Text>
</Pressable>
));
const styles = StyleSheet.create({
card: { padding: 16, borderRadius: 8, backgroundColor: '#fff' },
title: { fontSize: 16, fontWeight: '600' },
});
// Always provide keyExtractor and getItemLayout when possible
<FlatList
data={items}
keyExtractor={(item) => item.id}
renderItem={({ item }) => <ItemRow item={item} />}
getItemLayout={(_, index) => ({ length: ITEM_HEIGHT, offset: ITEM_HEIGHT * index, index })}
initialNumToRender={10}
maxToRenderPerBatch={10}
windowSize={5}
removeClippedSubviews
/>
hooks/useDebounce.ts
export function useDebounce<T>(value: T, delay: number): T {
const [debounced, setDebounced] = useState(value);
useEffect(() => {
const timer = setTimeout(() => setDebounced(value), delay);
return () => clearTimeout(timer);
}, [value, delay]);
return debounced;
}
  • Wrap all list items in memo() — prevents re-renders on parent state changes
  • Use useCallback for event handlers passed as props
  • StyleSheet.create() over inline styles — processed once, not per render
  • Prefer Pressable over TouchableOpacity (new API, more flexible)
  • Use useWindowDimensions() for responsive sizing — not Dimensions.get()
  • FlatList inside ScrollView causes infinite height issues — use nestedScrollEnabled or restructure
  • keyExtractor must return unique strings — never use array index for dynamic lists
  • memo() only does shallow comparison — use useMemo for derived objects passed as props
  • StyleSheet.absoluteFillObject is { position: 'absolute', top: 0, right: 0, bottom: 0, left: 0 }
  • Never render user-provided HTML — no dangerouslySetInnerHTML equivalent needed but sanitize text
  • Validate image URLs before passing to <Image source={{ uri }}> — reject javascript: URIs