# Top 30 questions d'entretien React : guide complet pour réussir
> Les 30 questions d'entretien React les plus posées en 2026. Réponses détaillées, exemples de code et conseils pour décrocher votre poste de développeur React.
- Published: 2026-01-31
- Updated: 2026-03-31
- Author: SharpSkill
- Tags: react interview, frontend interview, react questions, javascript, entretien technique
- Reading time: 18 min
---
Les entretiens techniques React évaluent la compréhension des concepts fondamentaux, des patterns avancés et des bonnes pratiques. Ce guide présente les 30 questions les plus fréquentes, avec des réponses détaillées et des exemples de code pour se préparer efficacement.
> **Conseil de préparation**
>
> Ces questions sont classées par niveau de difficulté. Commencer par maîtriser les fondamentaux avant d'aborder les concepts avancés permet une préparation plus structurée.
## Fondamentaux React
### 1. Qu'est-ce que le Virtual DOM et pourquoi React l'utilise ?
Le Virtual DOM est une représentation JavaScript légère du DOM réel. React utilise cette abstraction pour optimiser les mises à jour de l'interface.
Le processus fonctionne en trois étapes : React crée d'abord une copie virtuelle du DOM, puis compare cette copie avec la version précédente lors des changements (algorithme de diffing), et enfin applique uniquement les modifications nécessaires au DOM réel (reconciliation).
```jsx
// Exemple simplifié du concept
// Quand l'état change, React ne recrée pas tout le DOM
function Counter() {
const [count, setCount] = useState(0)
// Seul le span contenant count sera mis à jour dans le DOM réel
// Le reste du composant n'est pas touché
return (
Compteur
{count}
)
}
```
Cette approche évite les opérations DOM coûteuses et permet des mises à jour performantes même pour des interfaces complexes.
### 2. Quelle est la différence entre un composant fonctionnel et un composant classe ?
Les composants fonctionnels sont des fonctions JavaScript qui reçoivent des props et retournent du JSX. Depuis React 16.8, les hooks permettent d'utiliser l'état et le cycle de vie dans les composants fonctionnels.
```jsx
// Composant fonctionnel (recommandé)
// Plus concis, plus facile à tester, supporte les hooks
function Welcome({ name }) {
const [visits, setVisits] = useState(0)
useEffect(() => {
setVisits(v => v + 1)
}, [])
return
Bonjour {name}, visite #{visits}
}
// Composant classe (legacy)
// Plus verbeux, nécessite la gestion du this
class WelcomeClass extends React.Component {
state = { visits: 0 }
componentDidMount() {
this.setState(prev => ({ visits: prev.visits + 1 }))
}
render() {
return
}
}
```
Les composants fonctionnels sont aujourd'hui le standard. Les composants classe restent supportés mais ne sont plus recommandés pour les nouveaux projets.
### 3. Comment fonctionne le JSX ?
JSX est une extension syntaxique de JavaScript qui permet d'écrire du markup dans le code. Ce n'est pas du HTML mais du JavaScript déguisé.
```jsx
// Ce que nous écrivons (JSX)
const element = (
Titre
Paragraphe
)
// Ce que Babel compile (JavaScript pur)
const element = React.createElement(
'div',
{ className: 'container' },
React.createElement('h1', null, 'Titre'),
React.createElement('p', null, 'Paragraphe')
)
```
Les différences avec HTML incluent : `className` au lieu de `class`, `htmlFor` au lieu de `for`, le camelCase pour les attributs (`onClick`, `tabIndex`), et la fermeture obligatoire des balises auto-fermantes.
### 4. Qu'est-ce que le state et les props ?
Les props sont des données passées d'un composant parent à un enfant. Elles sont en lecture seule. Le state est l'état interne d'un composant, modifiable via des setters.
```jsx
// UserCard.jsx
// name et role sont des props (immuables)
function UserCard({ name, role }) {
// isExpanded est du state (mutable)
const [isExpanded, setIsExpanded] = useState(false)
return (
{name}
{role}
{/* Modifier le state déclenche un re-render */}
{isExpanded && }
)
}
// Utilisation
```
La règle fondamentale : les props descendent (parent → enfant), le state est local à chaque composant.
### 5. Pourquoi les clés (keys) sont-elles importantes dans les listes ?
Les clés aident React à identifier quels éléments ont changé, été ajoutés ou supprimés dans une liste. Sans clés uniques et stables, React peut avoir des comportements inattendus.
```jsx
// ❌ Mauvaise pratique : index comme clé
// Problème : si l'ordre change, React perd le tracking
{items.map((item, index) => (
))}
// ✅ Bonne pratique : identifiant unique et stable
{items.map(item => (
))}
// Exemple concret du problème avec les index
function TodoList() {
const [todos, setTodos] = useState([
{ id: 1, text: 'Apprendre React' },
{ id: 2, text: 'Créer un projet' }
])
// En supprimant le premier élément avec key={index}
// React pensera que l'élément 0 a changé de contenu
// au lieu de comprendre que l'élément a été supprimé
return (
{todos.map(todo => (
{todo.text}
))}
)
}
```
## Hooks React
### 6. Expliquez useState et ses pièges courants
`useState` permet de gérer l'état local d'un composant fonctionnel. Le setter peut prendre une valeur ou une fonction de mise à jour.
```jsx
// Déclaration avec valeur initiale
const [count, setCount] = useState(0)
// ❌ Piège : mises à jour multiples dans le même cycle
function increment() {
setCount(count + 1) // count = 0, définit 1
setCount(count + 1) // count = 0 encore, définit 1
setCount(count + 1) // count = 0 encore, définit 1
// Résultat final : 1 (pas 3)
}
// ✅ Solution : utiliser la fonction de mise à jour
function incrementCorrect() {
setCount(prev => prev + 1) // 0 → 1
setCount(prev => prev + 1) // 1 → 2
setCount(prev => prev + 1) // 2 → 3
// Résultat final : 3
}
// ❌ Piège : mutation d'objet
const [user, setUser] = useState({ name: 'Alice', age: 25 })
user.age = 26 // Mutation directe, pas de re-render
// ✅ Solution : créer un nouvel objet
setUser({ ...user, age: 26 })
// ou
setUser(prev => ({ ...prev, age: 26 }))
```
### 7. Comment fonctionne useEffect et son tableau de dépendances ?
`useEffect` permet d'exécuter des effets de bord après le rendu. Le tableau de dépendances contrôle quand l'effet s'exécute.
```jsx
// Exécuté à chaque rendu (rare, à éviter généralement)
useEffect(() => {
console.log('Rendu effectué')
})
// Exécuté uniquement au montage (équivalent componentDidMount)
useEffect(() => {
console.log('Composant monté')
// Cleanup au démontage (équivalent componentWillUnmount)
return () => {
console.log('Composant démonté')
}
}, [])
// Exécuté quand userId change
useEffect(() => {
async function fetchUser() {
const response = await fetch(`/api/users/${userId}`)
const data = await response.json()
setUser(data)
}
fetchUser()
}, [userId])
// ❌ Dépendance manquante - bug subtil
useEffect(() => {
const timer = setInterval(() => {
setCount(count + 1) // count est "capturé" à sa valeur initiale
}, 1000)
return () => clearInterval(timer)
}, []) // count manque dans les dépendances
// ✅ Correction avec fonction de mise à jour
useEffect(() => {
const timer = setInterval(() => {
setCount(prev => prev + 1) // Pas besoin de count dans les deps
}, 1000)
return () => clearInterval(timer)
}, [])
```
> **Règle ESLint**
>
> Toujours activer `eslint-plugin-react-hooks` pour détecter les dépendances manquantes. Cette règle prévient de nombreux bugs difficiles à diagnostiquer.
### 8. Quand utiliser useMemo et useCallback ?
Ces hooks permettent la mémorisation pour éviter des recalculs ou re-créations inutiles. Attention à ne pas en abuser.
```jsx
// useMemo : mémorise une valeur calculée
function ProductList({ products, filter }) {
// Recalculé uniquement si products ou filter changent
const filteredProducts = useMemo(() => {
console.log('Filtrage en cours...')
return products.filter(p => p.category === filter)
}, [products, filter])
return
{filteredProducts.map(p =>
{p.name}
)}
}
// useCallback : mémorise une fonction
function ParentComponent() {
const [count, setCount] = useState(0)
// Sans useCallback, handleClick est recréé à chaque rendu
// Causant des re-renders inutiles de ExpensiveChild
const handleClick = useCallback((id) => {
console.log('Clicked:', id)
}, []) // Dépendances vides = fonction stable
return (
<>
{count}
{/* React.memo sur ExpensiveChild pour que ça soit efficace */}
>
)
}
// ❌ Sur-optimisation : pas besoin ici
const SimpleComponent = () => {
// Ce calcul est trivial, useMemo ajoute de l'overhead
const doubled = useMemo(() => 2 * 2, [])
return {doubled}
}
```
Utiliser ces hooks uniquement quand un problème de performance est identifié ou pour stabiliser les références passées à des composants mémoïsés.
### 9. Comment fonctionne useRef et ses cas d'usage ?
`useRef` crée une référence mutable qui persiste entre les rendus sans déclencher de re-render quand elle change.
```jsx
// Cas 1 : Accéder à un élément DOM
function TextInput() {
const inputRef = useRef(null)
const focusInput = () => {
inputRef.current.focus()
}
return (
<>
>
)
}
// Cas 2 : Stocker une valeur mutable sans re-render
function Timer() {
const [seconds, setSeconds] = useState(0)
const intervalRef = useRef(null)
const start = () => {
// Stocker l'ID de l'interval pour pouvoir l'arrêter
intervalRef.current = setInterval(() => {
setSeconds(s => s + 1)
}, 1000)
}
const stop = () => {
clearInterval(intervalRef.current)
}
return (
{seconds}s
)
}
// Cas 3 : Garder la valeur précédente
function usePrevious(value) {
const ref = useRef()
useEffect(() => {
ref.current = value
}, [value])
return ref.current
}
```
### 10. Expliquez useContext et quand l'utiliser
`useContext` permet d'accéder à un contexte React sans prop drilling. Idéal pour des données globales comme le thème ou l'utilisateur connecté.
```jsx
// 1. Créer le contexte
const ThemeContext = createContext({
theme: 'light',
toggleTheme: () => {}
})
// 2. Créer le provider
function ThemeProvider({ children }) {
const [theme, setTheme] = useState('light')
const toggleTheme = useCallback(() => {
setTheme(prev => prev === 'light' ? 'dark' : 'light')
}, [])
// Mémoriser la valeur pour éviter les re-renders inutiles
const value = useMemo(() => ({ theme, toggleTheme }), [theme, toggleTheme])
return (
{children}
)
}
// 3. Utiliser le contexte
function ThemedButton() {
const { theme, toggleTheme } = useContext(ThemeContext)
return (
)
}
// 4. Wrapper l'application
function App() {
return (
)
}
```
## Patterns avancés
### 11. Qu'est-ce qu'un Higher-Order Component (HOC) ?
Un HOC est une fonction qui prend un composant et retourne un nouveau composant enrichi. Pattern moins utilisé depuis les hooks mais toujours présent dans certaines bibliothèques.
```jsx
// HOC qui ajoute des logs
function withLogging(WrappedComponent) {
return function WithLogging(props) {
useEffect(() => {
console.log(`${WrappedComponent.name} monté avec props:`, props)
return () => {
console.log(`${WrappedComponent.name} démonté`)
}
}, [])
return
}
}
// HOC qui gère l'authentification
function withAuth(WrappedComponent) {
return function WithAuth(props) {
const { user, isLoading } = useAuth()
if (isLoading) return
if (!user) return
return
}
}
// Utilisation
const ProtectedDashboard = withAuth(Dashboard)
const LoggedButton = withLogging(Button)
```
### 12. Expliquez le pattern Render Props
Le pattern Render Props permet de partager de la logique entre composants via une prop qui est une fonction.
```jsx
// Composant avec render prop
function MouseTracker({ render }) {
const [position, setPosition] = useState({ x: 0, y: 0 })
useEffect(() => {
const handleMove = (e) => {
setPosition({ x: e.clientX, y: e.clientY })
}
window.addEventListener('mousemove', handleMove)
return () => window.removeEventListener('mousemove', handleMove)
}, [])
// Appelle la fonction render avec les données
return render(position)
}
// Utilisation
function App() {
return (
(
Position : {x}, {y}
)}
/>
)
}
// Version moderne avec hook personnalisé (préférée)
function useMousePosition() {
const [position, setPosition] = useState({ x: 0, y: 0 })
useEffect(() => {
const handleMove = (e) => {
setPosition({ x: e.clientX, y: e.clientY })
}
window.addEventListener('mousemove', handleMove)
return () => window.removeEventListener('mousemove', handleMove)
}, [])
return position
}
function App() {
const { x, y } = useMousePosition()
return
Position : {x}, {y}
}
```
### 13. Comment créer un hook personnalisé ?
Les hooks personnalisés permettent d'extraire et réutiliser de la logique stateful entre composants.
```jsx
// useLocalStorage.js
function useLocalStorage(key, initialValue) {
// Initialiser avec la valeur du localStorage ou la valeur par défaut
const [storedValue, setStoredValue] = useState(() => {
try {
const item = window.localStorage.getItem(key)
return item ? JSON.parse(item) : initialValue
} catch (error) {
console.error(error)
return initialValue
}
})
// Wrapper du setter qui synchronise avec localStorage
const setValue = useCallback((value) => {
try {
// Supporter les fonctions de mise à jour
const valueToStore = value instanceof Function ? value(storedValue) : value
setStoredValue(valueToStore)
window.localStorage.setItem(key, JSON.stringify(valueToStore))
} catch (error) {
console.error(error)
}
}, [key, storedValue])
return [storedValue, setValue]
}
// Utilisation
function Settings() {
const [theme, setTheme] = useLocalStorage('theme', 'light')
const [fontSize, setFontSize] = useLocalStorage('fontSize', 16)
return (
setFontSize(Number(e.target.value))}
/>
)
}
```
### 14. Qu'est-ce que le Compound Components Pattern ?
Ce pattern permet de créer des composants qui fonctionnent ensemble de manière implicite, comme les balises `