Questions
These components duplicate stateful logic. Refactor them using a custom Hook.
You’re building a React application and notice a pattern: you have several components that need to manage a simple boolean isOn state and a function to toggle that state.
For example, you have a Toggle component that turns something on/off, and you’re about to build a VisibilityToggle component that also needs the exact same isOn state and toggle function. You’re about to copy-paste the useState and toggle logic, which is a clear sign of code duplication.
Your task is to refactor the application to eliminate this duplicated stateful logic.
- Create a custom Hook called
useTogglethat encapsulates theisOnstate and thetogglefunction. - Apply this
useToggleHook to both theTogglecomponent and theVisibilityTogglecomponent.
The functionality of both components should remain identical, but the underlying code should be cleaner and more reusable.
import React, { useState } from 'react';
// Component 1: Manages its own boolean state
function Toggle() {
const [isOn, setIsOn] = useState(false);
const handleToggle = () => {
setIsOn(prevIsOn => !prevIsOn);
};
return (
<div style={{ border: '1px solid #ccc', padding: '10px', margin: '10px' }}>
<h2>Toggle Component</h2>
<p>Status: {isOn ? 'ON' : 'OFF'}</p>
<button onClick={handleToggle}>Toggle</button>
</div>
);
}
// Component 2: Manages its own boolean state (duplicates logic from Toggle)
function VisibilityToggle() {
const [isVisible, setIsVisible] = useState(false); // Same logic as isOn
const handleToggleVisibility = () => {
setIsVisible(prevIsVisible => !prevIsVisible);
};
return (
<div style={{ border: '1px solid #ccc', padding: '10px', margin: '10px' }}>
<h2>Visibility Toggle Component</h2>
<p>Content is: {isVisible ? 'Visible' : 'Hidden'}</p>
<button onClick={handleToggleVisibility}>Toggle Visibility</button>
{isVisible && <p>This content is now visible!</p>}
</div>
);
}
export default function App() {
return (
<div>
<Toggle />
<VisibilityToggle />
</div>
);
} How Different Experience Levels Approach This
import React, { useState } from 'react'; // Component 1: Manages its own boolean state function Toggle() { const [isOn, setIsOn] = useState(false); const handleToggle = () => { setIsOn(prevIsOn => !prevIsOn); }; return ( <div style={{ border: '1px solid #ccc', padding: '10px', margin: '10px' }}> <h2>Toggle Component</h2> <p>Status: {isOn ? 'ON' : 'OFF'}</p> <button onClick={handleToggle}>Toggle</button> </div> ); } // Component 2: Manages its own boolean state (duplicates logic from Toggle) function VisibilityToggle() { const [isVisible, setIsVisible] = useState(false); // Same logic as isOn const handleToggleVisibility = () => { setIsVisible(prevIsVisible => !prevIsVisible); }; return ( <div style={{ border: '1px solid #ccc', padding: '10px', margin: '10px' }}> <h2>Visibility Toggle Component</h2> <p>Content is: {isVisible ? 'Visible' : 'Hidden'}</p> <button onClick={handleToggleVisibility}>Toggle Visibility</button> {isVisible && <p>This content is now visible!</p>} </div> ); } export default function App() { return ( <div> <Toggle /> <VisibilityToggle /> </div> ); }
import React, { useState } from 'react'; // 1. Create the custom Hook: useToggle function useToggle(initialValue = false) { const [isOn, setIsOn] = useState(initialValue); const toggle = () => { setIsOn(prevIsOn => !prevIsOn); }; return [isOn, toggle]; // Return the state and the toggler function } // Component 1: Now uses the custom Hook function Toggle() { const [isOn, toggle] = useToggle(false); // Use the custom Hook return ( <div style={{ border: '1px solid #ccc', padding: '10px', margin: '10px' }}> <h2>Toggle Component</h2> <p>Status: {isOn ? 'ON' : 'OFF'}</p> <button onClick={toggle}>Toggle</button> </div> ); } // Component 2: Now uses the custom Hook function VisibilityToggle() { const [isVisible, toggleVisibility] = useToggle(false); // Use the custom Hook return ( <div style={{ border: '1px solid #ccc', padding: '10px', margin: '10px' }}> <h2>Visibility Toggle Component</h2> <p>Content is: {isVisible ? 'Visible' : 'Hidden'}</p> <button onClick={toggleVisibility}>Toggle Visibility</button> {isVisible && <p>This content is now visible!</p>} </div> ); } export default function App() { return ( <div> <Toggle /> <VisibilityToggle /> </div> ); }
- Context over facts: Explains when and why, not just what
- Real examples: Provides specific use cases from production experience
- Trade-offs: Acknowledges pros, cons, and decision factors
Practice Question
What is the primary benefit of creating a custom Hook in React?