Advies voor het implementeren van React Error Boundaries voor robuuste foutafhandeling
description
Met deze prompt krijg je praktische hulp om React Error Boundaries te implementeren, waardoor je app stabieler wordt en beter met fouten omgaat zonder te crashen. Dit verbetert de gebruikerservaring en maakt onderhoud eenvoudiger.
prompt
Help me bij het implementeren van React Error Boundaries om mijn React-applicatie robuuster te maken door fouten in componenten af te handelen zonder de hele app te laten ...
try_prompt
generate_helper
disclaimerOnPageApi
tags
ai_answers
provider: openai
model: gpt-4.1-nano
Natuurlijk! React Error Boundaries zijn een krachtige manier om fouten in componenten op te vangen en te voorkomen dat de hele applicatie crasht. Ze worden geïmplementeerd door een component te maken die de lifecycle methoden `componentDidCatch` en `getDerivedStateFromError` gebruikt. Hier zijn de beste praktijken en een voorbeeld:
**Beste praktijken voor React Error Boundaries:**
1. **Gebruik een aparte Error Boundary component**: Maak een globale of specifieke Error Boundary die je rondom onderdelen van je app plaatst.
2. **Plaats Error Boundaries strategisch**: Bijvoorbeeld rondom complexe componenten of delen waar fouten kunnen optreden.
3. **Toon gebruikersvriendelijke foutmeldingen**: Geef een nette foutboodschap zonder technische details.
4. **Log fouten**: Stuur fouten naar een loggingdienst voor later onderzoek.
5. **Herstelopties bieden**: Bijvoorbeeld een knop om te proberen de component opnieuw te laden.
---
### Voorbeeld van een Error Boundary component:
```jsx
import React from 'react';
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false, error: null, errorInfo: null };
}
static getDerivedStateFromError(error) {
// Update state zodat de fallback UI getoond wordt
return { hasError: true, error };
}
componentDidCatch(error, errorInfo) {
// Log de error naar een externe service
console.error("Fout opgetreden:", error, errorInfo);
// eventueel: stuur naar logging service
}
handleReset = () => {
this.setState({ hasError: false, error: null, errorInfo: null });
}
render() {
if (this.state.hasError) {
// Fallback UI
return (
<div style={{ padding: '20px', background: '#fdd', border: '1px solid #f00' }}>
<h2>Er is een fout opgetreden.</h2>
<button onClick={this.handleReset}>Probeer opnieuw</button>
</div>
);
}
return this.props.children;
}
}
export default ErrorBoundary;
```
---
### Hoe te gebruiken:
Plaats de Error Boundary rondom componenten waar je fouten wilt opvangen, bijvoorbeeld:
```jsx
import ErrorBoundary from './ErrorBoundary';
import MijnComponent from './MijnComponent';
function App() {
return (
<ErrorBoundary>
<MijnComponent />
</ErrorBoundary>
);
}
```
Of voor geneste componenten:
```jsx
<ErrorBoundary>
<GedeelteVanDeApp />
</ErrorBoundary>
```
---
### Aanvullende tips:
- Voor API-fouten kan je ook foutafhandeling in je componenten zelf implementeren met `try-catch` of conditioneel renderen op foutstatus.
- Overweeg ook om meerdere Error Boundaries te gebruiken in plaats van één globale, zodat niet de hele app stopt bij een fout in één onderdeel.
- Combineer Error Boundaries met een fallback UI die gebruikers informeert en eventueel herstelt.
---
Door deze aanpak te volgen maak je je React-app robuuster en verbeter je de gebruikerservaring, zelfs wanneer er fouten optreden.
provider: deepseek
model: deepseek-chat
Zeker! Ik help je met het implementeren van React Error Boundaries om je applicatie robuuster te maken. Hier zijn de beste praktijken en voorbeeldcode.
## Beste praktijken voor Error Boundaries:
1. **Plaatsing strategisch**: Wrap alleen specifieke componentenbomen, niet de hele app
2. **Fallback UI**: Toon een gebruiksvriendelijke foutmelding
3. **Fout logging**: Log fouten naar een monitoring service
4. **Reset functionaliteit**: Voorzie een manier om de boundary te resetten
5. **Gebruik klasse-componenten**: Error Boundaries moeten klasse-componenten zijn
## Basisimplementatie:
```jsx
import React from 'react';
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = {
hasError: false,
error: null,
errorInfo: null
};
}
static getDerivedStateFromError(error) {
return { hasError: true };
}
componentDidCatch(error, errorInfo) {
this.setState({
error: error,
errorInfo: errorInfo
});
// Log de fout naar een monitoring service
console.error('Error Boundary caught an error:', error, errorInfo);
}
resetError = () => {
this.setState({
hasError: false,
error: null,
errorInfo: null
});
};
render() {
if (this.state.hasError) {
return (
<div style={{ padding: '20px', border: '1px solid #ff6b6b', margin: '10px' }}>
<h2>Er is iets misgegaan!</h2>
<details style={{ whiteSpace: 'pre-wrap' }}>
{this.state.error && this.state.error.toString()}
<br />
{this.state.errorInfo.componentStack}
</details>
<button
onClick={this.resetError}
style={{
marginTop: '10px',
padding: '8px 16px',
backgroundColor: '#4ecdc4',
color: 'white',
border: 'none',
borderRadius: '4px',
cursor: 'pointer'
}}
>
Probeer opnieuw
</button>
</div>
);
}
return this.props.children;
}
}
export default ErrorBoundary;
```
## Gebruik in je componentenstructuur:
```jsx
// App.js - Wrap gevoelige componentenbomen
import React from 'react';
import ErrorBoundary from './ErrorBoundary';
import UserProfile from './components/UserProfile';
import Dashboard from './components/Dashboard';
import ApiComponent from './components/ApiComponent';
function App() {
return (
<div className="App">
<ErrorBoundary>
<Header />
</ErrorBoundary>
<main>
<ErrorBoundary>
<Dashboard />
</ErrorBoundary>
{/* Aparte boundary voor elke kritieke sectie */}
<ErrorBoundary>
<UserProfile />
</ErrorBoundary>
<ErrorBoundary>
<ApiComponent />
</ErrorBoundary>
</main>
</div>
);
}
```
## Specifieke API Error Boundary:
```jsx
// ApiErrorBoundary.js - Gespecialiseerd voor API-fouten
import React from 'react';
class ApiErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = {
hasError: false,
retryCount: 0
};
}
static getDerivedStateFromError(error) {
if (error.message.includes('API') || error.message.includes('network')) {
return { hasError: true };
}
// Re-throw niet-API fouten
throw error;
}
componentDidCatch(error, errorInfo) {
console.error('API Error:', error);
if (this.state.retryCount < 3) {
setTimeout(() => {
this.setState(prevState => ({
retryCount: prevState.retryCount + 1,
hasError: false
}));
}, 1000 * this.state.retryCount);
}
}
render() {
if (this.state.hasError) {
if (this.state.retryCount >= 3) {
return (
<div style={{ padding: '20px', textAlign: 'center' }}>
<h3>Service tijdelijk niet beschikbaar</h3>
<p>Probeer het later opnieuw</p>
<button onClick={() => window.location.reload()}>
Vernieuw pagina
</button>
</div>
);
}
return (
<div style={{ padding: '20px', textAlign: 'center' }}>
<p>Bezig met verbinden... ({this.state.retryCount + 1}/3)</p>
</div>
);
}
return this.props.children;
}
}
```
## Gebruik met API-componenten:
```jsx
// components/UserProfile.js
import React, { useState, useEffect } from 'react';
import ApiErrorBoundary from './ApiErrorBoundary';
const UserProfile = () => {
const [userData, setUserData] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
const fetchUserData = async () => {
try {
const response = await fetch('/api/user');
if (!response.ok) {
throw new Error(`API Error: ${response.status}`);
}
const data = await response.json();
setUserData(data);
} catch (error) {
throw new Error(`Failed to load user data: ${error.message}`);
} finally {
setLoading(false);
}
};
fetchUserData();
}, []);
if (loading) return <div>Loading...</div>;
return (
<ApiErrorBoundary>
<div>
<h2>Profiel</h2>
{/* Je component logica hier */}
</div>
</ApiErrorBoundary>
);
};
```
## Geavanceerde strategieën:
1. **Hiërarchische boundaries**:
```jsx
<ErrorBoundary> {/* Hoog niveau */}
<Section>
<ErrorBoundary> {/* Sectie niveau */}
<Component>
<ErrorBoundary> {/* Component niveau */}
<UnstableFeature />
</ErrorBoundary>
</Component>
</ErrorBoundary>
</Section>
</ErrorBoundary>
```
2. **Context-aware boundaries**:
```jsx
class ContextAwareErrorBoundary extends React.Component {
componentDidCatch(error, errorInfo) {
// Gebruik React Context om foutstatus door te geven
this.props.onError(error, errorInfo);
}
// ... rest van de implementatie
}
```
## Belangrijke beperkingen:
- Error Boundaries vangen **geen** fouten in:
- Event handlers
- Asynchrone code (setTimeout, promises)
- Server-side rendering
- Errors in de error boundary zelf
Voor asynchrone fouten moet je traditionele try/catch gebruiken in combinatie met Error Boundaries.
Deze implementatie zorgt ervoor dat je app niet volledig crasht bij fouten in geneste componenten!