Composants React
Les composants React sont les blocs de construction de base des applications React. Un composant peut être compris comme une unité d'interface utilisateur réutilisable et indépendante. Chaque composant encapsule sa propre structure, ses styles, sa logique et son état.
Les composants React sont la pierre angulaire de la construction d'applications. Un composant peut être aussi petit qu'un bouton ou aussi grand qu'une page entière.

Les composants peuvent être divisés en :Composants fonctionnelsetComposants de classe。
Techniquement, un composant React est une fonction ou une classe JavaScript qui renvoie un élément React (généralement du JSX).
// 最简单的组件
function Hello() {
return <h1>Hello, World!</h1>;
}
Décomposez une interface utilisateur complexe en un arbre de composants :
App ├── Header │ ├── Logo │ └── Navigation │ ├── NavItem │ └── NavItem ├── Main │ ├── Sidebar │ └── Content │ ├── Article │ └── Article └── Footer
Composants fonctionnels
Les composants fonctionnels sont une manière concise de définir des composants.
Un composant fonctionnel est une fonction JavaScript qui accepte des props et renvoie un élément React.
Syntaxe de base :
// 方式 1:函数声明
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
// 方式 2:箭头函数
const Welcome = (props) => {
return <h1>Hello, {props.name}</h1>;
};
// 方式 3:简化写法(单行返回)
const Welcome = (props) => <h1>Hello, {props.name}</h1>;
Créez un composant fonctionnel simple :
Fichier src/Welcome.js :
// Définir un composant fonctionnel
function Welcome(props) {
return <h1>Bonjour, {props.name}!</h1>;
}
export default Welcome;
Affichez le composant dans src/index.js :
Fichier src/index.js :
import ReactDOM from 'react-dom';
import './index.css';
import Welcome from './Welcome';
const root = ReactDOM.createRoot(document.getElementById("root"));
// Afficher le composant Welcome et passer la prop name
root.render(<Welcome name="Monde" />);
Cet exemple montre un composant simple qui accepte une prop name et affiche "Bonjour, le monde !" sur la page.
Composants de classe
Les composants de classe sont définis à l'aide de la syntaxe de classe ES6, généralement utilisés lorsque vous devez gérer l'état ou utiliser des méthodes de cycle de vie.
Syntaxe de base :
import React, { Component } from 'react';
class Welcome extends Component {
render() {
return <h1>Hello, {this.props.name}</h1>;
}
}
Créez un composant de classe :
Exemple
class Welcome extends Component {
render() {
return <h1>Hello, {this.props.name}!</h1>;
}
}
export default Welcome;
Affichez le composant dans src/index.js :
Exemple
import ReactDOM from 'react-dom';
import './index.css';
import Welcome from './Welcome';
const root = ReactDOM.createRoot(document.getElementById("root"));
// Afficher le composant Welcome et passer la prop name
root.render(<Welcome name="Monde" />);
Exemple de test
Ensuite, nous allons créer un composant qui affiche "Hello World!", nommé HelloMessage :
Exemple React
Essayez-le »
Analyse de l'exemple :
1. Nous pouvons définir un composant à l'aide d'une fonction :
function HelloMessage(props) {
return <h1>Hello World!</h1>;
}
Vous pouvez également utiliser une classe ES6 pour définir un composant :
class Welcome extends React.Component {
render() {
return <h1>Hello World!</h1>;
}
}
2, const element = <HelloMessage />est un composant défini par l'utilisateur.
Notez que les noms d'éléments HTML natifs commencent par des lettres minuscules, alors que les noms de classes React personnalisées commencent par des lettres majuscules. Par exemple, HelloMessage ne peut pas être écrit sous la forme helloMessage. De plus, une classe de composant ne peut contenir qu'une seule balise de premier niveau ; sinon, une erreur sera signalée.
Si nous devons passer des paramètres à un composant, nous pouvons utiliser l'objetthis.props, exemple comme suit :
Exemple React
Essayez-le »
Dans l'exemple ci-dessus, la propnameest obtenue viaprops.name.
Remarque : lors de l'ajout d'attributs, l'attribut class doit être écrit className, et l'attribut for doit être écrit htmlFor. En effet, class et for sont des mots réservés en JavaScript.
Composants composites
Nous pouvons combiner plusieurs composants pour créer un seul composant, c'est-à-dire séparer les différents aspects fonctionnels d'un composant.
L'exemple suivant implémente un composant qui affiche le nom du site Web et l'URL :
Exemple React
Essayez-le »
Dans l'exemple, le composant App utilise les composants Name, Url et Nickname pour afficher les informations correspondantes.
Props (Propriétés)
Les props sont un moyen de transmettre des données entre les composants, comme les paramètres d'une fonction.
Utilisation de base
// 父组件传递 props
function App() {
return (
<div>
<Greeting name="Alice" age={25} />
<Greeting name="Bob" age={30} />
</div>
);
}
// 子组件接收 props
function Greeting(props) {
return (
<div>
<h1>Hello, {props.name}!</h1>
<p>Age: {props.age}</p>
</div>
);
}
Déstructuration des props
// 推荐:直接解构
function Greeting({ name, age }) {
return (
<div>
<h1>Hello, {name}!</h1>
<p>Age: {age}</p>
</div>
);
}
// 带默认值的解构
function Button({ text = "Submit", variant = "primary", disabled = false }) {
return (
<button className={variant} disabled={disabled}>
{text}
</button>
);
}
Types de props
Les props peuvent être n'importe quelle valeur JavaScript:
function Demo() {
const user = { name: "Alice", age: 25 };
const numbers = [1, 2, 3, 4, 5];
const handleClick = () => alert("Clicked!");
return (
<MyComponent
// 字符串
title="Hello"
// 数字
count={42}
// 布尔值
isActive={true}
// 数组
items={numbers}
// 对象
user={user}
// 函数
onClick={handleClick}
// JSX
children={<p>This is content</p>}
/>
);
}
Props children
Props spéciales utilisées pour transmettre le contenu enfant d'un composant:
// 方式 1:使用 props.children
function Card(props) {
return (
<div className="card">
<div className="card-body">
{props.children}
</div>
</div>
);
}
// 方式 2:解构 children
function Card({ children, title }) {
return (
<div className="card">
{title && <h2>{title}</h2>}
<div className="card-body">{children}</div>
</div>
);
}
// 使用
function App() {
return (
<Card title="My Card">
<p>This is the card content</p>
<button>Click me</button>
</Card>
);
}
Immutabilité des props
Principe important: Ne jamais modifier les props!
// 错误:修改 props
function BadComponent(props) {
props.name = "Changed"; // 绝对不要这样做!
return <h1>{props.name}</h1>;
}
// 正确:将 props 视为只读
function GoodComponent({ name }) {
const displayName = name.toUpperCase(); // 创建新值
return <h1>{displayName}</h1>;
}
Composition et réutilisation des composants
Patron de composition
// 基础组件
function Avatar({ src, alt }) {
return <img src={src} alt={alt} className="avatar" />;
}
function UserInfo({ name, email }) {
return (
<div>
<h3>{name}</h3>
<p>{email}</p>
</div>
);
}
// 组合成复杂组件
function UserCard({ user }) {
return (
<div className="user-card">
<Avatar src={user.avatar} alt={user.name} />
<UserInfo name={user.name} email={user.email} />
</div>
);
}
Patron de composant conteneur
// 容器组件:处理逻辑和状态
function Panel({ title, children, collapsible = false }) {
const [isOpen, setIsOpen] = useState(true);
return (
<div className="panel">
<div className="panel-header">
<h2>{title}</h2>
{collapsible && (
<button onClick={() => setIsOpen(!isOpen)}>
{isOpen ? "Collapse" : "Expand"}
</button>
)}
</div>
{isOpen && (
<div className="panel-content">
{children}
</div>
)}
</div>
);
}
// 使用
function App() {
return (
<Panel title="Settings" collapsible>
<p>Your settings here...</p>
</Panel>
);
}
Concept de composant d'ordre supérieur (implémenté par composition)
// 通用的加载状态包装
function WithLoading({ isLoading, children }) {
if (isLoading) {
return <div>Loading...</div>;
}
return children;
}
// 使用
function UserList({ users, isLoading }) {
return (
<WithLoading isLoading={isLoading}>
<ul>
{users.map(user => (
<li key={user.id}>{user.name}</li>
))}
</ul>
</WithLoading>
);
}
Conventions de nommage des composants
Règles de nommage
// 正确:大写字母开头(PascalCase)
function UserProfile() { }
function BlogPost() { }
function NavBar() { }
// 错误:小写字母开头
function userProfile() { } // React 会将其视为 HTML 标签
Nommage des fichiers
// 推荐的文件结构 src/ ├── components/ │ ├── Button.jsx // ou Button.js │ ├── UserCard.jsx │ ├── Navigation/ │ │ ├── Navigation.jsx │ │ ├── NavItem.jsx │ │ └── index.js // 导出 Navigation
Exporter et importer des composants
Export par défaut
// Button.jsx
export default function Button({ text }) {
return <button>{text}</button>;
}
// App.jsx
import Button from './Button';
Export nommé
// components.jsx
export function Button({ text }) {
return <button>{text}</button>;
}
export function Input({ value, onChange }) {
return <input value={value} onChange={onChange} />;
}
// App.jsx
import { Button, Input } from './components';
Export mixte
// Card.jsx
export default function Card({ children }) {
return <div className="card">{children}</div>;
}
export function CardHeader({ title }) {
return <div className="card-header">{title}</div>;
}
export function CardBody({ children }) {
return <div className="card-body">{children}</div>;
}
// App.jsx
import Card, { CardHeader, CardBody } from './Card';
Principes de conception des composants
1. Principe de responsabilité unique
Chaque composant doit faire une seule chose.
// 不好:组件做太多事情
function UserDashboard() {
// 获取用户数据
// 处理表单
// 显示图表
// 处理导航
// ...
}
// 好:拆分成多个组件
function UserDashboard() {
return (
<div>
<UserProfile />
<UserStats />
<UserActivity />
</div>
);
}
2. Garder les composants simples
Le code d'un composant ne doit pas dépasser 200 à 300 lignes.
// 好:提取子组件
function ProductCard({ product }) {
return (
<div className="product-card">
<ProductImage src={product.image} />
<ProductInfo name={product.name} price={product.price} />
<ProductActions productId={product.id} />
</div>
);
}
3. Utiliser les props de manière raisonnable
Ne pas passer trop de props.
// 不好:props 过多
function User({ name, age, email, address, phone, company, role, ... }) { }
// 好:使用对象
function User({ user }) {
const { name, age, email } = user;
// ...
}
4. Éviter une imbrication profonde
Une imbrication de composants excessivement profonde peut entraîner le problème de props drilling.
// 问题:props 需要层层传递
<App>
<Layout user={user}>
<Sidebar user={user}>
<Menu user={user}>
<MenuItem user={user} />
</Menu>
</Sidebar>
</Layout>
</App>
// 解决:使用 Context 或状态管理
Autres extensions