Komponenter: Återanvändbara UI-byggstenar
Komponenter låter dig dela upp UI:t i oberoende, återanvändbara delar och tänka på varje del isolerat. Den här sidan ger en introduktion till idén om komponenter.
Mål: Lära dig skapa, organisera och återanvända komponenter för att bygga skalbar React-kod.
Definiera en Komponent
React-komponenter är JavaScript-funktioner som returnerar markup:
function MyButton() {
return (
<button>Jag är en knapp</button>
);
}
Nu när du har deklarerat MyButton
kan du nästla den i en annan komponent:
function MyApp() {
return (
<div>
<h1>Välkommen till min app</h1>
<MyButton />
</div>
);
}
Observera att <MyButton />
börjar med stor bokstav. Så här vet du att det är en React-komponent. React-komponentnamn måste alltid börja med stor bokstav, medan HTML-taggar måste vara små bokstäver.
Komponenter inom komponenter
Komponenter är vanliga JavaScript-funktioner, så du kan hålla flera komponenter i samma fil:
function Avatar() {
return (
<img
className="avatar"
src="https://i.imgur.com/1bX5QH6.jpg"
alt="Lin Lanying"
width={100}
height={100}
/>
);
}
function Profile() {
return (
<div>
<Avatar />
<Avatar />
<Avatar />
</div>
);
}
I detta exempel har Profile
-komponenten tre Avatar
-komponenter.
Funktionella Komponenter: Det Moderna Sättet
Sedan React 16.8 och introduktionen av Hooks är funktionella komponenter standardsättet att skriva React-kod.
Grundläggande Komponent
// Enkel funktionell komponent
function Greeting() {
return <h1>Hej världen!</h1>;
}
// Arrow function syntax (också vanlig)
const Greeting = () => {
return <h1>Hej världen!</h1>;
};
// Kort syntax för enkel return
const Greeting = () => <h1>Hej världen!</h1>;
Komponent med Logik
function UserProfile() {
const user = {
name: "Anna Andersson",
age: 28,
email: "anna@example.com",
avatar: "/images/anna.jpg"
};
const isAdult = user.age >= 18;
return (
<div className="user-profile">
<img src={user.avatar} alt={`${user.name}s avatar`} />
<h2>{user.name}</h2>
<p>Ålder: {user.age} {isAdult && "✅ Myndig"}</p>
<p>E-post: {user.email}</p>
</div>
);
}
Exportera och Importera Komponenter
Magin med komponenter ligger i deras återanvändbarhet: du kan skapa komponenter som består av andra komponenter. Men när du nästlar fler och fler komponenter är det ofta vettigt att börja dela upp dem i olika filer. Detta låter dig hålla dina filer lätta att skanna och återanvända komponenter på fler ställen.
// Gallery.js
import Profile from './Profile.js';
function Gallery() {
return (
<section>
<h1>Fantastiska forskare</h1>
<Profile />
<Profile />
<Profile />
</section>
);
}
export default Gallery;
// Profile.js
function Profile() {
return (
<img
src="https://i.imgur.com/QIrZWGIs.jpg"
alt="Alan L. Hart"
/>
);
}
export default Profile;
// App.js
import Gallery from './Gallery.js';
function App() {
return (
<Gallery />
);
}
export default App;
Komponentens Anatomi
En React-komponent består av några viktiga delar:
// 1. Import-statements (om du använder andra komponenter)
import { useState } from 'react';
import './Button.css';
// 2. Komponentfunktionen
function Button() {
// 3. Logik (variabler, funktioner)
const handleClick = () => {
alert('Knappen klickades!');
};
// 4. Return-statement med JSX
return (
<button onClick={handleClick}>
Klicka mig
</button>
);
}
// 5. Export-statement
export default Button;
Klasskomponenter: Det Äldre Sättet
Före hooks använde React klasskomponenter för att hantera state och lifecycle. Du kommer fortfarande stöta på dem i äldre kodbaser.
import React, { Component } from 'react';
class ClassCounter extends Component {
constructor(props) {
super(props);
this.state = {
count: 0
};
}
// Lifecycle-metod
componentDidMount() {
console.log('Component har monterats');
}
componentDidUpdate(prevProps, prevState) {
if (prevState.count !== this.state.count) {
console.log(`Count ändrades från ${prevState.count} till ${this.state.count}`);
}
}
componentWillUnmount() {
console.log('Component kommer att avmonteras');
}
// Event handler
incrementCount = () => {
this.setState({ count: this.state.count + 1 });
}
render() {
return (
<div>
<h2>Räknare: {this.state.count}</h2>
<button onClick={this.incrementCount}>
Öka
</button>
</div>
);
}
}
Organisera Komponenter
När din app växer är det viktigt att organisera komponenter på ett smart sätt:
Fil-per-komponent (Rekommenderat)
src/
components/
Button/
Button.jsx
Button.css
Button.test.js
Avatar/
Avatar.jsx
Avatar.css
Card/
Card.jsx
Card.css
pages/
Home.jsx
About.jsx
App.jsx
Flera komponenter per fil (För små, relaterade komponenter)
// components/UI.jsx
export function Button({ children, onClick, type = "button" }) {
return (
<button type={type} onClick={onClick} className="btn">
{children}
</button>
);
}
export function Input({ placeholder, value, onChange }) {
return (
<input
className="input"
placeholder={placeholder}
value={value}
onChange={onChange}
/>
);
}
export function Card({ children }) {
return (
<div className="card">
{children}
</div>
);
}
Komponent-komposition
En av Reacts starkaste funktioner är komposition - att bygga komplexa komponenter från enklare komponenter:
function WelcomeMessage({ name }) {
return <h1>Hej {name}!</h1>;
}
function UserAvatar({ imageUrl, name }) {
return (
<img
src={imageUrl}
alt={name}
className="avatar"
/>
);
}
function UserCard({ user }) {
return (
<div className="user-card">
<UserAvatar imageUrl={user.avatar} name={user.name} />
<WelcomeMessage name={user.name} />
<p>E-post: {user.email}</p>
</div>
);
}
// Användning
function App() {
const user = {
name: "Anna Andersson",
email: "anna@example.com",
avatar: "/anna.jpg"
};
return <UserCard user={user} />;
}
Best Practices för Komponenter
1. Håll Komponenter Små och Fokuserade
// ❌ För stor komponent
function BlogPost({ post, user, comments, relatedPosts }) {
return (
<article>
{/* Hundratals rader kod... */}
</article>
);
}
// ✅ Uppdelade komponenter
function BlogPost({ post }) {
return (
<article>
<BlogHeader post={post} />
<BlogContent content={post.content} />
<BlogFooter postId={post.id} />
</article>
);
}
function BlogHeader({ post }) {
return (
<header>
<h1>{post.title}</h1>
<AuthorInfo author={post.author} />
<PublishDate date={post.publishedAt} />
</header>
);
}
2. Använda PropTypes för Typkontroll (Optional)
PropTypes är ett verktyg för typkontroll i React som hjälper dig att:
-
Hitta buggar tidigt: Genom att validera props under utveckling upptäcks fel direkt istället för att de dyker upp i produktion.
-
Dokumentera komponenter: PropTypes fungerar som självdokumenterande kod - andra utvecklare kan snabbt se vilka props en komponent förväntar sig.
-
Förbättra underhållbarhet: När du ändrar en komponent varnar PropTypes om du råkar skicka fel datatyp eller glömmer en required prop.
-
Underlätta refaktorering: Med tydliga kontrakt mellan komponenter blir det säkrare att göra större kodändringar.
Exempel på vanliga PropTypes:
import PropTypes from 'prop-types';
function ProductCard({ name, price, image, onSale }) {
return (
<div className="product-card">
<img src={image} alt={name} />
<h3>{name}</h3>
<p className={onSale ? "sale-price" : "regular-price"}>
{price} kr
</p>
</div>
);
}
ProductCard.propTypes = {
name: PropTypes.string.isRequired,
price: PropTypes.number.isRequired,
image: PropTypes.string.isRequired,
onSale: PropTypes.bool
};
ProductCard.defaultProps = {
onSale: false
};
Ett vanligt alternativ till PropTypes är TypeScript som erbjuder statisk typkontroll under kompilering och ger bättre IDE-stöd med autocompletions och refaktoreringsmöjligheter. TypeScript är särskilt användbart i större projekt där PropTypes kan bli otillräckligt.
3. Komponentnamnskonventioner
// ✅ PascalCase för komponenter
function UserProfile() { }
function ProductCard() { }
function NavigationMenu() { }
// ✅ camelCase för funktioner och variabler
const handleClick = () => { };
const userName = "Anna";
const isLoading = true;
// ✅ Beskrivande namn
function LoadingSpinner() { } // Bättre än Spinner()
function ErrorMessage() { } // Bättre än Error()
Sammanfattning
Komponenter är byggstenen i React-applikationer:
- Komponenter är JavaScript-funktioner som returnerar JSX
- Komponentnamn måste börja med stor bokstav
- Import/Export låter dig organisera komponenter i separata filer
- Komposition bygger komplexa UI från enkla komponenter
- Håll komponenter små och fokuserade på en sak
Vad händer härnäst?
Nu när du kan skapa komponenter är det dags att göra dem interaktiva! I nästa avsnitt lär du dig:
- Props - skicka data mellan komponenter
- State - ge komponenter minne
- Events - reagera på användarinteraktion
Gå vidare till State och Props för att lära dig hur du gör dina komponenter levande!