シンプルなプロフィールカードの構成
View、Text、Imageを組み合わせて、アバター、名前、自己紹介を表示するプロフィールカードコンポーネントを構築し、コンポーネント合成のスキルを身につけます
「シンプルなプロフィールカードの構成」はCoddyKit上の無料React Native Academyレッスンです。 これはレッスン4/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはReact Native Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 React Native Academyコースには全4レッスンが含まれています。
このレッスンの一部はまだ翻訳されておらず、英語で表示されています。
Component Composition in React Native
Composition means building big UI from small pieces. A profile card mixes a View, an Image, and Text — and once built, you can reuse it for every user.
// The goal: a reusable ProfileCard component
// that accepts props and renders a complete card UI
// Usage:
<ProfileCard
name='Alice Johnson'
role='Senior Developer'
bio='Building great mobile apps with React Native.'
avatarUri='https://i.pravatar.cc/150?img=1'
followers={1240}
/>Planning the Card Layout
Before coding, plan the card: avatar, name, role, bio, maybe a stats row. A column for the overall layout, a row for side-by-side bits. A quick sketch saves time.
// Conceptual structure (pseudo-code)
<View card>
<Image avatar />
<Text name />
<Text role />
<Text bio />
<View statsRow>
<View stat><Text number/><Text label/></View>
<View stat><Text number/><Text label/></View>
<View stat><Text number/><Text label/></View>
</View>
</View>Building the Card Container
Start with the card container View. Add borderRadius for rounded corners, a shadow for lift, and padding inside. Center the children with alignItems.
import { View, StyleSheet } from 'react-native';
export default function ProfileCard({ children }) {
return (
<View style={styles.card}>
{children}
</View>
);
}
const styles = StyleSheet.create({
card: {
backgroundColor: '#fff',
borderRadius: 20,
padding: 24,
marginHorizontal: 20,
marginVertical: 12,
alignItems: 'center',
shadowColor: '#000',
shadowOffset: { width: 0, height: 4 },
shadowOpacity: 0.1,
shadowRadius: 12,
elevation: 5,
},
});Adding the Avatar Image
Add the avatar at the top: a square View with borderRadius half its size and overflow: hidden makes it a circle. Take the image as a prop to stay reusable.
import { Image, View, StyleSheet } from 'react-native';
function Avatar({ uri, size = 90 }) {
const radius = size / 2;
return (
<View style={[
styles.ring,
{ width: size + 6, height: size + 6, borderRadius: radius + 3 }
]}>
<View style={[
styles.clip,
{ width: size, height: size, borderRadius: radius }
]}>
<Image source={{ uri }} style={{ width: size, height: size }} />
</View>
</View>
);
}
const styles = StyleSheet.create({
ring: { borderWidth: 3, borderColor: '#4f86f7', alignItems: 'center', justifyContent: 'center' },
clip: { overflow: 'hidden', backgroundColor: '#e0e0e0' },
});Name, Role, and Bio Text
Below the avatar, add three Text blocks: a big bold name, a smaller muted role, and a centered bio. A little marginTop between them sets a clean rhythm.
import { Text, StyleSheet } from 'react-native';
function CardInfo({ name, role, bio }) {
return (
<>
<Text style={styles.name}>{name}</Text>
<Text style={styles.role}>{role}</Text>
<Text style={styles.bio} numberOfLines={3}>{bio}</Text>
</>
);
}
const styles = StyleSheet.create({
name: { fontSize: 22, fontWeight: '700', color: '#111', marginTop: 14, textAlign: 'center' },
role: { fontSize: 14, color: '#4f86f7', fontWeight: '500', marginTop: 4, textAlign: 'center' },
bio: { fontSize: 14, color: '#666', lineHeight: 22, marginTop: 10, textAlign: 'center' },
});Stat Counter Row
Many cards end with a stats row: followers and posts side by side. Use flexDirection: row with justifyContent: space-around and a top border to set it off.
import { View, Text, StyleSheet } from 'react-native';
function StatRow({ followers, following, posts }) {
return (
<View style={styles.row}>
<Stat value={posts} label='Posts' />
<Stat value={followers} label='Followers' />
<Stat value={following} label='Following' />
</View>
);
}
function Stat({ value, label }) {
return (
<View style={styles.stat}>
<Text style={styles.value}>{value}</Text>
<Text style={styles.label}>{label}</Text>
</View>
);
}
const styles = StyleSheet.create({
row: { flexDirection: 'row', justifyContent: 'space-around', width: '100%', borderTopWidth: 1, borderTopColor: '#eee', marginTop: 20, paddingTop: 16 },
stat: { alignItems: 'center' },
value: { fontSize: 18, fontWeight: '700', color: '#111' },
label: { fontSize: 12, color: '#999', marginTop: 2 },
});Assembling the Full ProfileCard
Now combine the parts into one ProfileCard that takes props and just renders them. No internal state — pure presentation makes it easy to reuse and test.
import { View, StyleSheet } from 'react-native';
import Avatar from './Avatar';
import CardInfo from './CardInfo';
import StatRow from './StatRow';
export default function ProfileCard({
name, role, bio, avatarUri, followers, following, posts
}) {
return (
<View style={styles.card}>
<Avatar uri={avatarUri} size={90} />
<CardInfo name={name} role={role} bio={bio} />
<StatRow followers={followers} following={following} posts={posts} />
</View>
);
}
const styles = StyleSheet.create({
card: {
backgroundColor: '#fff',
borderRadius: 20,
padding: 24,
marginHorizontal: 20,
alignItems: 'center',
elevation: 5,
shadowColor: '#000',
shadowOffset: { width: 0, height: 4 },
shadowOpacity: 0.1,
shadowRadius: 12,
},
});Rendering Multiple Cards in a List
To show many cards, map over an array of users. For long lists reach for FlatList; for a few, ScrollView is fine. Give each card a unique key.
import { ScrollView } from 'react-native';
import ProfileCard from './ProfileCard';
const users = [
{ id: '1', name: 'Alice', role: 'Designer', bio: 'Crafting beautiful UIs.', avatarUri: 'https://i.pravatar.cc/150?img=1', followers: 980, following: 210, posts: 45 },
{ id: '2', name: 'Bob', role: 'Developer', bio: 'Loves React Native and coffee.', avatarUri: 'https://i.pravatar.cc/150?img=2', followers: 1420, following: 380, posts: 73 },
];
export default function App() {
return (
<ScrollView style={{ backgroundColor: '#f5f5f5' }}>
{users.map(user => (
<ProfileCard key={user.id} {...user} />
))}
</ScrollView>
);
}Adding a Follow Button
Make it interactive with a Follow button using TouchableOpacity. Toggle the label and color, but keep the real API call in the parent via a callback.
import { TouchableOpacity, Text, StyleSheet } from 'react-native';
import { useState } from 'react';
export default function FollowButton({ onPress }) {
const [following, setFollowing] = useState(false);
function handlePress() {
setFollowing(prev => !prev);
onPress && onPress(!following);
}
return (
<TouchableOpacity
style={[styles.btn, following && styles.btnActive]}
onPress={handlePress}
>
<Text style={[styles.label, following && styles.labelActive]}>
{following ? 'Following' : 'Follow'}
</Text>
</TouchableOpacity>
);
}
const styles = StyleSheet.create({
btn: { borderWidth: 1.5, borderColor: '#4f86f7', borderRadius: 20, paddingHorizontal: 24, paddingVertical: 8, marginTop: 16 },
btnActive: { backgroundColor: '#4f86f7' },
label: { color: '#4f86f7', fontWeight: '600' },
labelActive: { color: '#fff' },
});Adding Accessibility to the Card
Make the card accessible: set accessible on the outer View with a label that sums it up, so screen readers announce the whole card as one clear unit.
import { View, Text, StyleSheet } from 'react-native';
export default function AccessibleProfileCard({ name, role, followers }) {
const label = `${name}, ${role}, ${followers} followers`;
return (
<View
style={styles.card}
accessible
accessibilityLabel={label}
accessibilityRole='summary'
>
<Text style={styles.name}>{name}</Text>
<Text style={styles.role}>{role}</Text>
<Text style={styles.followers}>{followers} followers</Text>
</View>
);
}
const styles = StyleSheet.create({
card: { padding: 16, borderRadius: 12, backgroundColor: '#fff', elevation: 3 },
name: { fontSize: 20, fontWeight: 'bold' },
role: { color: '#666', marginTop: 4 },
followers: { color: '#4f86f7', marginTop: 8 },
});Skeleton Loading State
While data loads, show a skeleton — grey pulsing boxes shaped like the card. It feels more polished than a spinner and hints at what is coming.
import { View, StyleSheet } from 'react-native';
export default function ProfileCardSkeleton() {
return (
<View style={styles.card}>
{/* Avatar placeholder */}
<View style={styles.avatarSkeleton} />
{/* Name placeholder */}
<View style={styles.nameSkeleton} />
{/* Role placeholder */}
<View style={styles.roleSkeleton} />
{/* Bio placeholder lines */}
<View style={[styles.bioSkeleton, { width: '100%' }]} />
<View style={[styles.bioSkeleton, { width: '80%' }]} />
</View>
);
}
const styles = StyleSheet.create({
card: { padding: 24, borderRadius: 20, backgroundColor: '#fff', alignItems: 'center', margin: 16, elevation: 3 },
avatarSkeleton: { width: 90, height: 90, borderRadius: 45, backgroundColor: '#e0e0e0' },
nameSkeleton: { width: 140, height: 22, borderRadius: 4, backgroundColor: '#e0e0e0', marginTop: 14 },
roleSkeleton: { width: 100, height: 16, borderRadius: 4, backgroundColor: '#e0e0e0', marginTop: 8 },
bioSkeleton: { height: 14, borderRadius: 4, backgroundColor: '#e0e0e0', marginTop: 8 },
});Quick Check
Quick check! See how your ProfileCard skills stack up. 🎉
Lesson Recap
Awesome — you composed a real card! You combined View, Text, and Image, used props to reuse it, and added skeletons for polish. Next up: StyleSheet and Flexbox.
よくある質問
「シンプルなプロフィールカードの構成」レッスンは無料ですか?
はい。「シンプルなプロフィールカードの構成」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、React Native Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 React Native Academyコースには全4レッスンが含まれています。
「シンプルなプロフィールカードの構成」で何を学びますか?
View、Text、Imageを組み合わせて、アバター、名前、自己紹介を表示するプロフィールカードコンポーネントを構築し、コンポーネント合成のスキルを身につけます ブラウザで直接実行するハンズオンコードでReact Native Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
React Native Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのReact Native Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン4/4です。
「シンプルなプロフィールカードの構成」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このReact Native Academyレッスンでコードを書いて実行できますか?
はい。すべてのReact Native Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- コンテナとしてのViewコンポーネント
- テキストの表示とフォントのスタイリング
- ローカルとリモートの画像の表示
- シンプルなプロフィールカードの構成