Avatar in React Native
Avatar
~9 Min. Lesezeit Zuletzt aktualisiert am August 8, 2026
An avatar shows a round profile picture – or, if none is available, a placeholder with the user's initials. Both cases can be covered by ONE reusable component.
1. Description
The circular crop comes from borderRadius set to exactly half the diameter (width/height: 48 → borderRadius: 24). For the initials fallback, the user's name is split into its words and the first letter of each is used.
2. Short example
<Image
source={{ uri: imageUrl }}
style={{ width: 48, height: 48, borderRadius: 24 }}
/>3. Complete project: a contact list with avatars
npx create-expo-app avatar-demo
cd avatar-demoimport { View, Image, Text, StyleSheet } from 'react-native';
const COLORS = ['#2563eb', '#16a34a', '#dc2626', '#9333ea', '#ea580c'];
function initialsOf(name) {
return name
.trim()
.split(/\s+/)
.slice(0, 2)
.map((word) => word[0]?.toUpperCase())
.join('');
}
function colorOf(name) {
const sum = [...name].reduce((acc, char) => acc + char.charCodeAt(0), 0);
return COLORS[sum % COLORS.length];
}
function Avatar({ name, imageUrl, size = 48 }) {
const style = { width: size, height: size, borderRadius: size / 2 };
if (imageUrl) {
return <Image source={{ uri: imageUrl }} style={style} />;
}
return (
<View style={[style, styles.placeholder, { backgroundColor: colorOf(name) }]}>
<Text style={[styles.initials, { fontSize: size * 0.4 }]}>
{initialsOf(name)}
</Text>
</View>
);
}
const styles = StyleSheet.create({
placeholder: { alignItems: 'center', justifyContent: 'center' },
initials: { color: 'white', fontWeight: 'bold' },
});
export default Avatar;import { View, Text, FlatList, StyleSheet } from 'react-native';
import Avatar from './components/Avatar';
const CONTACTS = [
{ id: '1', name: 'Anna Berger', imageUrl: 'https://i.pravatar.cc/150?img=5' },
{ id: '2', name: 'Mehmet Yildiz', imageUrl: null },
{ id: '3', name: 'Sophie Klein', imageUrl: null },
];
export default function App() {
return (
<FlatList
data={CONTACTS}
keyExtractor={(item) => item.id}
contentContainerStyle={styles.list}
renderItem={({ item }) => (
<View style={styles.row}>
<Avatar name={item.name} imageUrl={item.imageUrl} />
<Text style={styles.name}>{item.name}</Text>
</View>
)}
/>
);
}
const styles = StyleSheet.create({
list: { paddingTop: 60, paddingHorizontal: 16 },
row: { flexDirection: 'row', alignItems: 'center', paddingVertical: 10 },
name: { marginLeft: 12, fontSize: 16 },
});4. Explanation
imageUrl ? <Image .../> : <View .../>– the component decides ITSELF whether to render a real image or the initials placeholder; the caller doesn't need to know.colorOf(name)produces a deterministic (always the same) color per name – via the sum of character codes modulo the number of colors, instead of a random color on every render.size / 2instead of a fixed value makes the component reusable for different avatar sizes (e.g. small in a list, large on a profile screen) – ONEsizeprop drives width, height, AND rounding together.[...name].reduce(...)instead ofname.charCodeAtdirectly on the string, so it also works with names containing characters outside the basic Latin range (the spread operator splits correctly into individual characters).