Exemples Preact
Exemples du framework Preact incluant les composants, hooks, routing et patterns Preact modernes
Key Facts
- Category
- Web Frameworks
- Items
- 3
- Format Families
- text
Sample Overview
Exemples du framework Preact incluant les composants, hooks, routing et patterns Preact modernes This sample set belongs to Web Frameworks and can be used to test related workflows inside Elysia Tools.
💻 Preact Hello World javascript
🟢 simple
⭐
Exemples de composants Preact de base et application Hello World avec JSX
⏱️ 15 min
🏷️ preact, jsx, components, hooks
Prerequisites:
JavaScript basics, HTML basics
// Preact Hello World Examples
// 1. Basic functional component
import { h } from 'preact';
function HelloWorld() {
return <h1>Hello, World!</h1>;
}
// 2. Component with props
function Greeting({ name }) {
return <h1>Hello, {name}!</h1>;
}
// 3. Component with state
import { useState } from 'preact/hooks';
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<h1>Count: {count}</h1>
<button onClick={() => setCount(count + 1)}>
Increment
</button>
<button onClick={() => setCount(count - 1)}>
Decrement
</button>
</div>
);
}
// 4. Component with multiple states
function UserForm() {
const [name, setName] = useState('');
const [email, setEmail] = useState('');
const handleSubmit = (e) => {
e.preventDefault();
alert(`Name: ${name}, Email: ${email}`);
};
return (
<form onSubmit={handleSubmit}>
<div>
<label>Name: </label>
<input
type="text"
value={name}
onChange={(e) => setName(e.target.value)}
/>
</div>
<div>
<label>Email: </label>
<input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
</div>
<button type="submit">Submit</button>
</form>
);
}
// 5. Conditional rendering
function WelcomeMessage({ isLoggedIn }) {
return (
<div>
{isLoggedIn ? (
<h1>Welcome back!</h1>
) : (
<h1>Please sign in</h1>
)}
</div>
);
}
// 6. List rendering
function TodoList() {
const todos = [
{ id: 1, text: 'Learn Preact', completed: false },
{ id: 2, text: 'Build a project', completed: false },
{ id: 3, text: 'Deploy to production', completed: true }
];
return (
<ul>
{todos.map(todo => (
<li key={todo.id} style={{
textDecoration: todo.completed ? 'line-through' : 'none'
}}>
{todo.text}
</li>
))}
</ul>
);
}
// 7. Event handling
function ButtonExample() {
const handleClick = () => {
alert('Button clicked!');
};
const handleMouseOver = () => {
console.log('Mouse over button');
};
return (
<div>
<button onClick={handleClick}>
Click me
</button>
<button onMouseOver={handleMouseOver}>
Hover over me
</button>
</div>
);
}
// 8. Component with useEffect
import { useEffect } from 'preact/hooks';
function Timer() {
const [seconds, setSeconds] = useState(0);
useEffect(() => {
const interval = setInterval(() => {
setSeconds(seconds => seconds + 1);
}, 1000);
return () => clearInterval(interval);
}, []);
return (
<div>
<h1>Timer: {seconds}s</h1>
</div>
);
}
// 9. Fetching data with useEffect
function UserProfile({ userId }) {
const [user, setUser] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
fetch(`https://jsonplaceholder.typicode.com/users/${userId}`)
.then(response => response.json())
.then(data => {
setUser(data);
setLoading(false);
})
.catch(error => {
console.error('Error fetching user:', error);
setLoading(false);
});
}, [userId]);
if (loading) return <div>Loading...</div>;
if (!user) return <div>User not found</div>;
return (
<div>
<h2>{user.name}</h2>
<p>Email: {user.email}</p>
<p>Phone: {user.phone}</p>
<p>Website: {user.website}</p>
</div>
);
}
// 10. Custom hook example
function useCounter(initialValue = 0) {
const [count, setCount] = useState(initialValue);
const increment = () => setCount(count + 1);
const decrement = () => setCount(count - 1);
const reset = () => setCount(initialValue);
return { count, increment, decrement, reset };
}
function CustomCounter() {
const { count, increment, decrement, reset } = useCounter(10);
return (
<div>
<h1>Count: {count}</h1>
<button onClick={increment}>+</button>
<button onClick={decrement}>-</button>
<button onClick={reset}>Reset</button>
</div>
);
}
// 11. Component composition
function Card({ title, children }) {
return (
<div style={{
border: '1px solid #ccc',
borderRadius: '8px',
padding: '16px',
margin: '16px'
}}>
<h3>{title}</h3>
{children}
</div>
);
}
function App() {
return (
<div>
<Card title="Welcome">
<p>This is a card component with children.</p>
<HelloWorld />
</Card>
<Card title="Counter">
<Counter />
</Card>
<Card title="Timer">
<Timer />
</Card>
</div>
);
}
export {
HelloWorld,
Greeting,
Counter,
UserForm,
WelcomeMessage,
TodoList,
ButtonExample,
Timer,
UserProfile,
CustomCounter,
Card,
App
};
💻 Patterns de Hooks Preact javascript
🟡 intermediate
⭐⭐⭐
Exemples avancés de hooks Preact et patterns de gestion d'état
⏱️ 30 min
🏷️ preact, hooks, state, performance
Prerequisites:
Preact basics, JavaScript ES6+, State management concepts
// Preact Hooks Patterns and Advanced Examples
import { h, createContext, useContext } from 'preact';
import { useState, useEffect, useCallback, useMemo, useRef } from 'preact/hooks';
// 1. useContext Example
const ThemeContext = createContext();
function ThemeProvider({ children }) {
const [theme, setTheme] = useState('light');
const toggleTheme = () => {
setTheme(prevTheme => prevTheme === 'light' ? 'dark' : 'light');
};
return (
<ThemeContext.Provider value={{ theme, toggleTheme }}>
{children}
</ThemeContext.Provider>
);
}
function ThemedComponent() {
const { theme, toggleTheme } = useContext(ThemeContext);
const styles = {
backgroundColor: theme === 'light' ? '#fff' : '#333',
color: theme === 'light' ? '#333' : '#fff',
padding: '20px',
borderRadius: '8px'
};
return (
<div style={styles}>
<h2>Current Theme: {theme}</h2>
<button onClick={toggleTheme}>Toggle Theme</button>
</div>
);
}
// 2. Custom Hook: useLocalState
function useLocalState(key, initialValue) {
const [state, setState] = useState(() => {
try {
const item = localStorage.getItem(key);
return item ? JSON.parse(item) : initialValue;
} catch (error) {
console.error('Error reading localStorage:', error);
return initialValue;
}
});
const setLocalState = useCallback((value) => {
try {
const valueToStore = value instanceof Function ? value(state) : value;
setState(valueToStore);
localStorage.setItem(key, JSON.stringify(valueToStore));
} catch (error) {
console.error('Error setting localStorage:', error);
}
}, [key, state]);
return [state, setLocalState];
}
function LocalStorageExample() {
const [name, setName] = useLocalState('userName', '');
return (
<div>
<input
type="text"
value={name}
onChange={(e) => setName(e.target.value)}
placeholder="Enter your name"
/>
<p>Your name: {name}</p>
<p>(Persisted in localStorage)</p>
</div>
);
}
// 3. useReducer Pattern
function reducer(state, action) {
switch (action.type) {
case 'increment':
return { count: state.count + 1 };
case 'decrement':
return { count: state.count - 1 };
case 'reset':
return { count: 0 };
default:
throw new Error();
}
}
function useReducerDemo() {
const [state, dispatch] = useState({ count: 0 });
const increment = () => dispatch({ type: 'increment' });
const decrement = () => dispatch({ type: 'decrement' });
const reset = () => dispatch({ type: 'reset' });
return { count: state.count, increment, decrement, reset };
}
function ReducerExample() {
const { count, increment, decrement, reset } = useReducerDemo();
return (
<div>
<h1>Count: {count}</h1>
<button onClick={increment}>+</button>
<button onClick={decrement}>-</button>
<button onClick={reset}>Reset</button>
</div>
);
}
// 4. useMemo Example
function ExpensiveCalculation({ number }) {
const expensiveResult = useMemo(() => {
console.log('Running expensive calculation...');
let result = 0;
for (let i = 0; i < number * 100000; i++) {
result += Math.sqrt(i);
}
return Math.round(result);
}, [number]);
return (
<div>
<h3>Expensive Calculation Result: {expensiveResult}</h3>
<p>Input number: {number}</p>
</div>
);
}
// 5. useCallback Example
function ParentComponent() {
const [count, setCount] = useState(0);
const handleClick = useCallback(() => {
console.log('Button clicked! Count:', count);
}, [count]);
return (
<div>
<h1>Count: {count}</h1>
<button onClick={() => setCount(count + 1)}>
Increment
</button>
<ChildButton onClick={handleClick} />
</div>
);
}
// Memoized child component
function ChildButton({ onClick }) {
console.log('ChildButton rendered');
return <button onClick={onClick}>Child Button</button>;
}
// 6. useRef Example
function RefExample() {
const inputRef = useRef(null);
const countRef = useRef(0);
const focusInput = () => {
inputRef.current.focus();
};
const incrementRef = () => {
countRef.current += 1;
console.log('Ref count:', countRef.current);
};
return (
<div>
<input ref={inputRef} type="text" placeholder="Focus me" />
<button onClick={focusInput}>Focus Input</button>
<button onClick={incrementRef}>Increment Ref</button>
</div>
);
}
// 7. Custom Hook: useDebounce
function useDebounce(value, delay) {
const [debouncedValue, setDebouncedValue] = useState(value);
useEffect(() => {
const handler = setTimeout(() => {
setDebouncedValue(value);
}, delay);
return () => {
clearTimeout(handler);
};
}, [value, delay]);
return debouncedValue;
}
function SearchExample() {
const [searchTerm, setSearchTerm] = useState('');
const debouncedSearchTerm = useDebounce(searchTerm, 500);
useEffect(() => {
if (debouncedSearchTerm) {
console.log('Searching for:', debouncedSearchTerm);
// In real app, this would trigger an API call
}
}, [debouncedSearchTerm]);
return (
<div>
<input
type="text"
value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)}
placeholder="Search..."
/>
<p>Debounced search term: {debouncedSearchTerm}</p>
</div>
);
}
// 8. useLayoutEffect Example
function LayoutEffectExample() {
const [dimensions, setDimensions] = useState({ width: 0, height: 0 });
const divRef = useRef(null);
useEffect(() => {
if (divRef.current) {
const { clientWidth, clientHeight } = divRef.current;
setDimensions({ width: clientWidth, height: clientHeight });
}
}, []);
return (
<div>
<div
ref={divRef}
style={{
width: '300px',
height: '200px',
backgroundColor: 'lightblue',
padding: '20px'
}}
>
<h3>Component with Layout Effect</h3>
<p>Width: {dimensions.width}px</p>
<p>Height: {dimensions.height}px</p>
</div>
</div>
);
}
// 9. Custom Hook: useFetch
function useFetch(url) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
let isCancelled = false;
const fetchData = async () => {
try {
setLoading(true);
setError(null);
const response = await fetch(url);
const result = await response.json();
if (!isCancelled) {
setData(result);
}
} catch (err) {
if (!isCancelled) {
setError(err.message);
}
} finally {
if (!isCancelled) {
setLoading(false);
}
}
};
fetchData();
return () => {
isCancelled = true;
};
}, [url]);
return { data, loading, error };
}
function FetchExample() {
const { data, loading, error } = useFetch('https://jsonplaceholder.typicode.com/posts/1');
if (loading) return <div>Loading...</div>;
if (error) return <div>Error: {error}</div>;
return (
<div>
<h2>{data?.title}</h2>
<p>{data?.body}</p>
</div>
);
}
// 10. Performance Optimization Example
function OptimizedList({ items }) {
const renderItem = useCallback((item) => (
<li key={item.id}>
{item.name} - {item.category}
</li>
), []);
const memoizedItems = useMemo(() => {
return items.map(renderItem);
}, [items, renderItem]);
return <ul>{memoizedItems}</ul>;
}
function PerformanceExample() {
const [items, setItems] = useState([
{ id: 1, name: 'Item 1', category: 'A' },
{ id: 2, name: 'Item 2', category: 'B' },
{ id: 3, name: 'Item 3', category: 'C' }
]);
return (
<div>
<h2>Optimized List</h2>
<OptimizedList items={items} />
</div>
);
}
export {
ThemeProvider,
ThemedComponent,
LocalStorageExample,
ReducerExample,
ExpensiveCalculation,
ParentComponent,
ChildButton,
RefExample,
SearchExample,
LayoutEffectExample,
FetchExample,
PerformanceExample,
useLocalState,
useDebounce,
useFetch
};
💻 Routing Preact javascript
🟡 intermediate
⭐⭐⭐
Routing côté client dans Preact utilisant preact-router
⏱️ 25 min
🏷️ preact, routing, navigation, spa
Prerequisites:
Preact basics, JavaScript ES6+, SPA concepts
// Preact Routing Examples
import { h } from 'preact';
import { Router, route, Link } from 'preact-router';
// 1. Basic Route Components
function Home() {
return (
<div>
<h1>Home Page</h1>
<p>Welcome to our Preact application!</p>
</div>
);
}
function About() {
return (
<div>
<h1>About Us</h1>
<p>This is a sample Preact application with routing.</p>
</div>
);
}
function Contact() {
return (
<div>
<h1>Contact</h1>
<p>Get in touch with us!</p>
</div>
);
}
// 2. Dynamic Routes with Parameters
function UserProfile({ matches }) {
const userId = matches.user;
const [user, setUser] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
fetch(`https://jsonplaceholder.typicode.com/users/${userId}`)
.then(response => response.json())
.then(data => {
setUser(data);
setLoading(false);
})
.catch(error => {
console.error('Error fetching user:', error);
setLoading(false);
});
}, [userId]);
if (loading) return <div>Loading user profile...</div>;
if (!user) return <div>User not found</div>;
return (
<div>
<h1>User Profile</h1>
<h2>{user.name}</h2>
<p><strong>Email:</strong> {user.email}</p>
<p><strong>Phone:</strong> {user.phone}</p>
<p><strong>Website:</strong> {user.website}</p>
<p><strong>Company:</strong> {user.company.name}</p>
<Link href="/">← Back to Home</Link>
</div>
);
}
// 3. Blog Post Routes
function BlogPost({ matches }) {
const postId = matches.post;
const [post, setPost] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
fetch(`https://jsonplaceholder.typicode.com/posts/${postId}`)
.then(response => response.json())
.then(data => {
setPost(data);
setLoading(false);
})
.catch(error => {
console.error('Error fetching post:', error);
setLoading(false);
});
}, [postId]);
if (loading) return <div>Loading post...</div>;
if (!post) return <div>Post not found</div>;
return (
<div>
<h1>{post.title}</h1>
<p>{post.body}</p>
<Link href="/blog">← Back to Blog</Link>
</div>
);
}
function BlogList() {
const [posts, setPosts] = useState([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
fetch('https://jsonplaceholder.typicode.com/posts?_limit=10')
.then(response => response.json())
.then(data => {
setPosts(data);
setLoading(false);
})
.catch(error => {
console.error('Error fetching posts:', error);
setLoading(false);
});
}, []);
if (loading) return <div>Loading blog posts...</div>;
return (
<div>
<h1>Blog Posts</h1>
<ul>
{posts.map(post => (
<li key={post.id}>
<Link href={`/blog/${post.id}`}>{post.title}</Link>
</li>
))}
</ul>
<Link href="/">← Back to Home</Link>
</div>
);
}
// 4. Navigation Component
function Navigation() {
const [currentPath, setCurrentPath] = useState('/');
useEffect(() => {
// Handle route changes
const handleRoute = () => {
setCurrentPath(window.location.pathname);
};
// Listen for route changes
window.addEventListener('popstate', handleRoute);
handleRoute(); // Initial call
return () => {
window.removeEventListener('popstate', handleRoute);
};
}, []);
return (
<nav style={{
backgroundColor: '#333',
padding: '1rem',
marginBottom: '2rem'
}}>
<ul style={{
listStyle: 'none',
margin: 0,
padding: 0,
display: 'flex',
gap: '1rem'
}}>
<li>
<Link
href="/"
style={{
color: currentPath === '/' ? '#fff' : '#ccc',
textDecoration: 'none'
}}
>
Home
</Link>
</li>
<li>
<Link
href="/about"
style={{
color: currentPath === '/about' ? '#fff' : '#ccc',
textDecoration: 'none'
}}
>
About
</Link>
</li>
<li>
<Link
href="/blog"
style={{
color: currentPath.startsWith('/blog') ? '#fff' : '#ccc',
textDecoration: 'none'
}}
>
Blog
</Link>
</li>
<li>
<Link
href="/contact"
style={{
color: currentPath === '/contact' ? '#fff' : '#ccc',
textDecoration: 'none'
}}
>
Contact
</Link>
</li>
</ul>
</nav>
);
}
// 5. 404 Not Found Component
function NotFound() {
return (
<div>
<h1>404 - Page Not Found</h1>
<p>The page you're looking for doesn't exist.</p>
<Link href="/">← Go back to Home</Link>
</div>
);
}
// 6. Protected Route Example
function ProtectedRoute({ component: Component, ...rest }) {
const [isAuthenticated, setIsAuthenticated] = useState(false);
useEffect(() => {
// Check authentication status
const token = localStorage.getItem('authToken');
setIsAuthenticated(!!token);
}, []);
if (!isAuthenticated) {
return (
<div>
<h1>Authentication Required</h1>
<p>Please log in to access this page.</p>
<Link href="/login">Go to Login</Link>
</div>
);
}
return <Component {...rest} />;
}
function Dashboard() {
return (
<div>
<h1>Dashboard</h1>
<p>Welcome to your protected dashboard!</p>
<Link href="/">← Back to Home</Link>
</div>
);
}
function Login() {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const handleLogin = (e) => {
e.preventDefault();
// Simulate authentication
localStorage.setItem('authToken', 'fake-token');
route('/dashboard');
};
return (
<div>
<h1>Login</h1>
<form onSubmit={handleLogin}>
<div>
<label>Email:</label>
<input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
required
/>
</div>
<div>
<label>Password:</label>
<input
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
required
/>
</div>
<button type="submit">Login</button>
</form>
<Link href="/">← Back to Home</Link>
</div>
);
}
// 7. Main App Component with Router
function App() {
return (
<div>
<Navigation />
<Router>
<Home path="/" />
<About path="/about" />
<BlogList path="/blog" />
<BlogPost path="/blog/:post" />
<UserProfile path="/user/:user" />
<Contact path="/contact" />
<Login path="/login" />
<ProtectedRoute path="/dashboard" component={Dashboard} />
<NotFound default />
</Router>
</div>
);
}
// 8. Programmatic Navigation Example
function ProgrammaticNavigation() {
const navigateToProfile = () => {
route('/user/1');
};
const navigateWithDelay = () => {
setTimeout(() => {
route('/about');
}, 2000);
};
const goBack = () => {
window.history.back();
};
return (
<div>
<h1>Programmatic Navigation</h1>
<button onClick={navigateToProfile}>Go to User 1</button>
<button onClick={navigateWithDelay}>Go to About in 2 seconds</button>
<button onClick={goBack}>Go Back</button>
<Link href="/">← Back to Home</Link>
</div>
);
}
export {
App,
Navigation,
Home,
About,
Contact,
BlogList,
BlogPost,
UserProfile,
NotFound,
ProtectedRoute,
Dashboard,
Login,
ProgrammaticNavigation
};