// Création du contexte
const ThemeContext = React.createContext('light');
// Provider au niveau supérieur
function App() {
const [theme, setTheme] = useState('light');
return (
<ThemeContext.Provider value={{ theme, setTheme }}>
<Layout />
</ThemeContext.Provider>
);
}
// Utilisation du contexte
function Button() {
const { theme, setTheme } = useContext(ThemeContext);
return (
<button
className={`btn-${theme}`}
onClick={() => setTheme(
theme === 'light' ? 'dark' : 'light'
)}
>
Changer le thème
</button>
);
}
// Hook pour gérer un formulaire
function useForm(initialState = {}) {
const [values, setValues] = useState(initialState);
const handleChange = (e) => {
const { name, value } = e.target;
setValues(prev => ({
...prev,
[name]: value
}));
};
const resetForm = () => {
setValues(initialState);
};
return {
values,
handleChange,
resetForm
};
}
// Utilisation
function LoginForm() {
const {
values,
handleChange,
resetForm
} = useForm({
email: '',
password: ''
});
const handleSubmit = (e) => {
e.preventDefault();
// Traiter le formulaire
resetForm();
};
return (
<form onSubmit={handleSubmit}>
<input
name="email"
value={values.email}
onChange={handleChange}
/>
<input
name="password"
type="password"
value={values.password}
onChange={handleChange}
/>
<button type="submit">
Connexion
</button>
</form>
);
}
// Définir le reducer
const todoReducer = (state, action) => {
switch (action.type) {
case 'ADD_TODO':
return [...state, {
id: Date.now(),
text: action.payload,
completed: false
}];
case 'TOGGLE_TODO':
return state.map(todo =>
todo.id === action.payload
? { ...todo, completed: !todo.completed }
: todo
);
case 'DELETE_TODO':
return state.filter(
todo => todo.id !== action.payload
);
default:
return state;
}
};
// Utilisation dans un composant
function TodoList() {
const [todos, dispatch] = useReducer(
todoReducer,
[]
);
const addTodo = (text) => {
dispatch({
type: 'ADD_TODO',
payload: text
});
};
return (
<div>
<TodoForm onSubmit={addTodo} />
{todos.map(todo => (
<TodoItem
key={todo.id}
todo={todo}
onToggle={() => dispatch({
type: 'TOGGLE_TODO',
payload: todo.id
})}
onDelete={() => dispatch({
type: 'DELETE_TODO',
payload: todo.id
})}
/>
))}
</div>
);
}
const TodoItem = React.memo(({ todo, onToggle }) => (
<div>
<input
type="checkbox"
checked={todo.completed}
onChange={onToggle}
/>
<span>{todo.text}</span>
</div>
));
// Comparaison personnalisée
const areEqual = (prevProps, nextProps) => {
return prevProps.todo.id === nextProps.todo.id &&
prevProps.todo.completed ===
nextProps.todo.completed;
};
function TodoList({ todos, filter }) {
const filteredTodos = useMemo(() =>
todos.filter(todo =>
todo.status === filter
),
[todos, filter]
);
const handleToggle = useCallback((id) => {
toggleTodo(id);
}, []);
return (
<div>
{filteredTodos.map(todo => (
<TodoItem
key={todo.id}
todo={todo}
onToggle={handleToggle}
/>
))}
</div>
);
}