On our cosmic journey through the world of React, efficient use of resources is key to mission success. Just as space engineers use proven designs for different spaceship modules, we too can leverage design patterns in React to maximize code reusability and create more scalable applications.
Higher-Order Components (HOC) are functions that take a component and return a new, enhanced component. This is a pattern based on the principle of composition, not inheritance.
1// Simple HOC adding time tracking functionality
2function withTimer(WrappedComponent) {
3 return function WithTimer(props) {
4 const [startTime] = useState(Date.now());
5 const [currentTime, setCurrentTime] = useState(Date.now());
6
7 useEffect(() => {
8 const timer = setInterval(() => {
9 setCurrentTime(Date.now());
10 }, 1000);
11
12 return () => clearInterval(timer);
13 }, []);
14
15 const elapsedTime = (currentTime - startTime) / 1000;
16
17 return (
18 <WrappedComponent
19 {...props}
20 elapsedTime={elapsedTime}
21 />
22 );
23 };
24}
25
26// Using the HOC
27function MissionControl({ missionName, elapsedTime }) {
28 return (
29 <div className="mission-control">
30 <h2>Mission: {missionName}</h2>
31 <p>Duration: {elapsedTime.toFixed(0)} seconds</p>
32 {/* rest of component */}
33 </div>
34 );
35}
36
37const MissionControlWithTimer = withTimer(MissionControl);
38
39// Rendering the enhanced component
40function App() {
41 return <MissionControlWithTimer missionName="Apollo" />;
42}Render Props is a pattern where a component receives a function that tells it what to render. This allows logic to be shared between components.
1function MouseTracker({ render }) {
2 const [position, setPosition] = useState({ x: 0, y: 0 });
3
4 useEffect(() => {
5 function handleMouseMove(event) {
6 setPosition({
7 x: event.clientX,
8 y: event.clientY
9 });
10 }
11
12 window.addEventListener('mousemove', handleMouseMove);
13
14 return () => {
15 window.removeEventListener('mousemove', handleMouseMove);
16 };
17 }, []);
18
19 return render(position);
20}
21
22// Using render props
23function App() {
24 return (
25 <MouseTracker
26 render={({ x, y }) => (
27 <div className="space-map">
28 <h2>Star Map</h2>
29 <p>Cursor coordinates: ({x}, {y})</p>
30 <div
31 className="space-ship"
32 style={{
33 position: 'absolute',
34 left: x,
35 top: y
36 }}
37 >
38 🚀
39 </div>
40 </div>
41 )}
42 />
43 );
44}This pattern allows you to create components that work together while maintaining flexibility and code readability.
1function Spaceship({ children }) {
2 const [power, setPower] = useState(0);
3 const [shields, setShields] = useState(false);
4
5 const contextValue = {
6 power,
7 setPower,
8 shields,
9 setShields
10 };
11
12 return (
13 <SpaceshipContext.Provider value={contextValue}>
14 <div className="spaceship">
15 {children}
16 </div>
17 </SpaceshipContext.Provider>
18 );
19}
20
21// Child components
22Spaceship.Engine = function Engine() {
23 const { power, setPower } = useContext(SpaceshipContext);
24
25 return (
26 <div className="engine">
27 <h3>Engine</h3>
28 <p>Power: {power}%</p>
29 <input
30 type="range"
31 min="0"
32 max="100"
33 value={power}
34 onChange={e => setPower(Number(e.target.value))}
35 />
36 </div>
37 );
38};
39
40Spaceship.Shields = function Shields() {
41 const { shields, setShields } = useContext(SpaceshipContext);
42
43 return (
44 <div className="shields">
45 <h3>Shields</h3>
46 <button onClick={() => setShields(!shields)}>
47 {shields ? 'Deactivate' : 'Activate'} shields
48 </button>
49 <p>Status: {shields ? 'Active' : 'Inactive'}</p>
50 </div>
51 );
52};
53
54// Usage
55function App() {
56 return (
57 <Spaceship>
58 <h2>Spaceship Control Panel</h2>
59 <Spaceship.Engine />
60 <Spaceship.Shields />
61 </Spaceship>
62 );
63}Redux implements the Flux pattern, which assumes a unidirectional data flow. The application state is stored in a single object (store), and state modifications can only occur by dispatching actions that are processed by reducers.
1// Actions
2const ADD_CREWMEMBER = 'ADD_CREWMEMBER';
3const REMOVE_CREWMEMBER = 'REMOVE_CREWMEMBER';
4
5// Action creators
6function addCrewmember(member) {
7 return {
8 type: ADD_CREWMEMBER,
9 payload: member
10 };
11}
12
13function removeCrewmember(id) {
14 return {
15 type: REMOVE_CREWMEMBER,
16 payload: id
17 };
18}
19
20// Reducer
21function crewReducer(state = [], action) {
22 switch (action.type) {
23 case ADD_CREWMEMBER:
24 return [...state, action.payload];
25 case REMOVE_CREWMEMBER:
26 return state.filter(member => member.id !== action.payload);
27 default:
28 return state;
29 }
30}
31
32// In a component with react-redux
33function CrewManagement() {
34 const crew = useSelector(state => state.crew);
35 const dispatch = useDispatch();
36
37 function handleAddCrewmember() {
38 const newMember = {
39 id: Date.now(),
40 name: 'New crew member',
41 role: 'Cadet'
42 };
43 dispatch(addCrewmember(newMember));
44 }
45
46 return (
47 <div>
48 <h2>Crew Management</h2>
49 <button onClick={handleAddCrewmember}>Add crew member</button>
50 <ul>
51 {crew.map(member => (
52 <li key={member.id}>
53 {member.name} - {member.role}
54 <button onClick={() => dispatch(removeCrewmember(member.id))}>
55 Remove
56 </button>
57 </li>
58 ))}
59 </ul>
60 </div>
61 );
62}Context API allows passing data through the component tree without the need to pass props at every level.
1// Creating context
2const MissionContext = createContext();
3
4// Provider
5function MissionProvider({ children }) {
6 const [mission, setMission] = useState({
7 name: 'Apollo 11',
8 status: 'In progress',
9 crewMembers: [
10 { id: 1, name: 'Neil Armstrong', role: 'Commander' },
11 { id: 2, name: 'Buzz Aldrin', role: 'Lunar Module Pilot' },
12 { id: 3, name: 'Michael Collins', role: 'Command Module Pilot' }
13 ]
14 });
15
16 function updateMissionStatus(newStatus) {
17 setMission(prev => ({ ...prev, status: newStatus }));
18 }
19
20 function addCrewMember(member) {
21 setMission(prev => ({
22 ...prev,
23 crewMembers: [...prev.crewMembers, member]
24 }));
25 }
26
27 const value = {
28 mission,
29 updateMissionStatus,
30 addCrewMember
31 };
32
33 return (
34 <MissionContext.Provider value={value}>
35 {children}
36 </MissionContext.Provider>
37 );
38}
39
40// Custom hook for easier usage
41function useMission() {
42 const context = useContext(MissionContext);
43 if (!context) {
44 throw new Error('useMission must be used within a MissionProvider');
45 }
46 return context;
47}
48
49// Usage in components
50function MissionDashboard() {
51 const { mission } = useMission();
52
53 return (
54 <div>
55 <h1>Mission: {mission.name}</h1>
56 <p>Status: {mission.status}</p>
57 </div>
58 );
59}
60
61function MissionControl() {
62 const { updateMissionStatus } = useMission();
63
64 return (
65 <div>
66 <h2>Mission Control Center</h2>
67 <button onClick={() => updateMissionStatus('Completed successfully')}>
68 Complete mission
69 </button>
70 <button onClick={() => updateMissionStatus('Aborted')}>
71 Abort mission
72 </button>
73 </div>
74 );
75}
76
77function CrewList() {
78 const { mission, addCrewMember } = useMission();
79
80 return (
81 <div>
82 <h2>Mission Crew</h2>
83 <ul>
84 {mission.crewMembers.map(member => (
85 <li key={member.id}>
86 {member.name} - {member.role}
87 </li>
88 ))}
89 </ul>
90 <button
91 onClick={() =>
92 addCrewMember({
93 id: Date.now(),
94 name: 'New astronaut',
95 role: 'Mission Specialist'
96 })
97 }
98 >
99 Add crew member
100 </button>
101 </div>
102 );
103}
104
105// Putting it all together
106function App() {
107 return (
108 <MissionProvider>
109 <div className="mission-app">
110 <MissionDashboard />
111 <MissionControl />
112 <CrewList />
113 </div>
114 </MissionProvider>
115 );
116}As we saw in the previous module, custom hooks are a powerful tool for encapsulating and reusing state-related logic.
1function useSpaceshipSystems() {
2 const [engines, setEngines] = useState({
3 mainEngine: { power: 0, status: 'offline' },
4 leftThruster: { power: 0, status: 'offline' },
5 rightThruster: { power: 0, status: 'offline' }
6 });
7
8 const [lifeSupportSystem, setLifeSupportSystem] = useState({
9 oxygen: 100,
10 temperature: 21,
11 pressure: 1
12 });
13
14 function startEngine(engineName) {
15 setEngines(prev => ({
16 ...prev,
17 [engineName]: {
18 ...prev[engineName],
19 status: 'online',
20 power: 10
21 }
22 }));
23 }
24
25 function setEnginePower(engineName, power) {
26 if (engines[engineName].status === 'offline') {
27 console.warn(`Cannot set power - engine ${engineName} is offline`);
28 return;
29 }
30
31 setEngines(prev => ({
32 ...prev,
33 [engineName]: {
34 ...prev[engineName],
35 power: Math.max(0, Math.min(100, power))
36 }
37 }));
38 }
39
40 function stopEngine(engineName) {
41 setEngines(prev => ({
42 ...prev,
43 [engineName]: {
44 ...prev[engineName],
45 status: 'offline',
46 power: 0
47 }
48 }));
49 }
50
51 function adjustLifeSupport({ oxygen, temperature, pressure }) {
52 setLifeSupportSystem(prev => ({
53 ...prev,
54 ...(oxygen !== undefined ? { oxygen } : {}),
55 ...(temperature !== undefined ? { temperature } : {}),
56 ...(pressure !== undefined ? { pressure } : {})
57 }));
58 }
59
60 return {
61 engines,
62 lifeSupportSystem,
63 startEngine,
64 setEnginePower,
65 stopEngine,
66 adjustLifeSupport
67 };
68}
69
70// Usage
71function SpaceshipControls() {
72 const {
73 engines,
74 lifeSupportSystem,
75 startEngine,
76 setEnginePower,
77 stopEngine,
78 adjustLifeSupport
79 } = useSpaceshipSystems();
80
81 return (
82 <div className="spaceship-controls">
83 <h2>Ship Systems Control</h2>
84
85 <div className="engines-section">
86 <h3>Engines</h3>
87 {Object.entries(engines).map(([name, engine]) => (
88 <div key={name} className="engine-control">
89 <h4>{formatEngineName(name)}</h4>
90 <p>Status: {engine.status}</p>
91 <p>Power: {engine.power}%</p>
92
93 {engine.status === 'offline' ? (
94 <button onClick={() => startEngine(name)}>Start</button>
95 ) : (
96 <>
97 <input
98 type="range"
99 min="0"
100 max="100"
101 value={engine.power}
102 onChange={e => setEnginePower(name, Number(e.target.value))}
103 />
104 <button onClick={() => stopEngine(name)}>Stop</button>
105 </>
106 )}
107 </div>
108 ))}
109 </div>
110
111 <div className="life-support">
112 <h3>Life Support System</h3>
113 <p>Oxygen level: {lifeSupportSystem.oxygen}%</p>
114 <p>Temperature: {lifeSupportSystem.temperature}°C</p>
115 <p>Pressure: {lifeSupportSystem.pressure} atm</p>
116
117 <div className="controls">
118 <button
119 onClick={() =>
120 adjustLifeSupport({
121 oxygen: lifeSupportSystem.oxygen + 5
122 })
123 }
124 >
125 Increase oxygen level
126 </button>
127 <button
128 onClick={() =>
129 adjustLifeSupport({
130 temperature: lifeSupportSystem.temperature - 1
131 })
132 }
133 >
134 Lower temperature
135 </button>
136 </div>
137 </div>
138 </div>
139 );
140}
141
142function formatEngineName(name) {
143 return name
144 .replace(/([A-Z])/g, ' $1')
145 .replace(/^./, str => str.toUpperCase());
146}This pattern separates business logic (container) from presentation (presentational component), which increases component reusability and simplifies testing.
1// Container component - handles logic and data fetching
2function PlanetDataContainer({ planetId, children }) {
3 const [planet, setPlanet] = useState(null);
4 const [loading, setLoading] = useState(true);
5 const [error, setError] = useState(null);
6
7 useEffect(() => {
8 setLoading(true);
9
10 fetch(`https://api.planets.com/${planetId}`)
11 .then(response => {
12 if (!response.ok) throw new Error('Failed to fetch planet data');
13 return response.json();
14 })
15 .then(data => {
16 setPlanet(data);
17 setLoading(false);
18 })
19 .catch(err => {
20 setError(err.message);
21 setLoading(false);
22 });
23 }, [planetId]);
24
25 // Call children function with data
26 return children({ planet, loading, error });
27}
28
29// Presentational component - only handles display
30function PlanetInfo({ planet, loading, error }) {
31 if (loading) return <div>Loading planet data...</div>;
32 if (error) return <div>Error: {error}</div>;
33 if (!planet) return null;
34
35 return (
36 <div className="planet-info">
37 <h2>{planet.name}</h2>
38 <div className="planet-details">
39 <p>Type: {planet.type}</p>
40 <p>Diameter: {planet.diameter} km</p>
41 <p>Distance from Sun: {planet.distanceFromSun} million km</p>
42 <p>Orbital period: {planet.orbitalPeriod} days</p>
43 <p>Surface temperature: {planet.surfaceTemperature}°C</p>
44 </div>
45
46 {planet.moons && planet.moons.length > 0 && (
47 <div className="moons">
48 <h3>Moons ({planet.moons.length}):</h3>
49 <ul>
50 {planet.moons.map(moon => (
51 <li key={moon.id}>{moon.name}</li>
52 ))}
53 </ul>
54 </div>
55 )}
56 </div>
57 );
58}
59
60// Usage
61function SolarSystemExplorer() {
62 const [selectedPlanet, setSelectedPlanet] = useState('earth');
63
64 return (
65 <div className="solar-system-explorer">
66 <h1>Solar System Exploration</h1>
67
68 <div className="planet-selector">
69 <label>Select a planet: </label>
70 <select
71 value={selectedPlanet}
72 onChange={e => setSelectedPlanet(e.target.value)}
73 >
74 <option value="mercury">Mercury</option>
75 <option value="venus">Venus</option>
76 <option value="earth">Earth</option>
77 <option value="mars">Mars</option>
78 <option value="jupiter">Jupiter</option>
79 <option value="saturn">Saturn</option>
80 <option value="uranus">Uranus</option>
81 <option value="neptune">Neptune</option>
82 </select>
83 </div>
84
85 <PlanetDataContainer planetId={selectedPlanet}>
86 {({ planet, loading, error }) => (
87 <PlanetInfo planet={planet} loading={loading} error={error} />
88 )}
89 </PlanetDataContainer>
90 </div>
91 );
92}React prefers composition over inheritance. This pattern allows creating flexible components through nesting and passing props.
1// Base component - Card
2function Card({ title, children, footer, className }) {
3 return (
4 <div className={`card ${className || ''}`}>
5 {title && <div className="card-header">{title}</div>}
6 <div className="card-body">{children}</div>
7 {footer && <div className="card-footer">{footer}</div>}
8 </div>
9 );
10}
11
12// Specialized components using composition
13function MissionCard({ mission, onComplete }) {
14 return (
15 <Card
16 title={<h3>{mission.name}</h3>}
17 footer={
18 <button onClick={() => onComplete(mission.id)}>
19 Complete mission
20 </button>
21 }
22 className="mission-card"
23 >
24 <p><strong>Objective:</strong> {mission.objective}</p>
25 <p><strong>Status:</strong> {mission.status}</p>
26 <p><strong>Progress:</strong> {mission.progress}%</p>
27 <div className="progress-bar">
28 <div
29 className="progress"
30 style={{ width: `${mission.progress}%` }}
31 />
32 </div>
33 </Card>
34 );
35}
36
37function AstronautCard({ astronaut, onAssign }) {
38 return (
39 <Card
40 title={<h3>{astronaut.name}</h3>}
41 footer={
42 <button onClick={() => onAssign(astronaut.id)}>
43 Assign to mission
44 </button>
45 }
46 className="astronaut-card"
47 >
48 <div className="astronaut-info">
49 <img
50 src={astronaut.avatar}
51 alt={astronaut.name}
52 className="astronaut-avatar"
53 />
54 <div>
55 <p><strong>Rank:</strong> {astronaut.rank}</p>
56 <p><strong>Specialization:</strong> {astronaut.specialization}</p>
57 <p><strong>Missions:</strong> {astronaut.missionCount}</p>
58 </div>
59 </div>
60 </Card>
61 );
62}
63
64// Usage
65function Dashboard() {
66 const missions = [
67 { id: 1, name: 'Mars Exploration', objective: 'Explore the surface', status: 'In progress', progress: 65 },
68 { id: 2, name: 'ISS Space Station', objective: 'Module maintenance', status: 'Planned', progress: 0 }
69 ];
70
71 const astronauts = [
72 { id: 1, name: 'John Smith', rank: 'Captain', specialization: 'Pilot', missionCount: 5, avatar: '/avatars/js.png' },
73 { id: 2, name: 'Anna Johnson', rank: 'Lieutenant', specialization: 'Engineer', missionCount: 3, avatar: '/avatars/aj.png' }
74 ];
75
76 return (
77 <div className="dashboard">
78 <h1>Space Center Control Panel</h1>
79
80 <section className="missions-section">
81 <h2>Active Missions</h2>
82 <div className="missions-grid">
83 {missions.map(mission => (
84 <MissionCard
85 key={mission.id}
86 mission={mission}
87 onComplete={id => console.log(`Completed mission ${id}`)}
88 />
89 ))}
90 </div>
91 </section>
92
93 <section className="astronauts-section">
94 <h2>Available Astronauts</h2>
95 <div className="astronauts-grid">
96 {astronauts.map(astronaut => (
97 <AstronautCard
98 key={astronaut.id}
99 astronaut={astronaut}
100 onAssign={id => console.log(`Assigned astronaut ${id}`)}
101 />
102 ))}
103 </div>
104 </section>
105 </div>
106 );
107}This pattern separates the behavioral logic of a component from its appearance, allowing maximum styling flexibility.
1// Headless component - contains only logic, no UI
2function useTabControl(initialTab = 0) {
3 const [activeTab, setActiveTab] = useState(initialTab);
4
5 function activateTab(index) {
6 setActiveTab(index);
7 }
8
9 return {
10 activeTab,
11 activateTab
12 };
13}
14
15// Usage with any UI
16function MissionTabs() {
17 const tabs = [
18 { id: 'overview', label: 'Overview' },
19 { id: 'crew', label: 'Crew' },
20 { id: 'timeline', label: 'Timeline' },
21 { id: 'systems', label: 'Systems' }
22 ];
23
24 const { activeTab, activateTab } = useTabControl();
25
26 return (
27 <div className="mission-tabs">
28 <div className="tabs-header">
29 {tabs.map((tab, index) => (
30 <button
31 key={tab.id}
32 className={`tab-button ${activeTab === index ? 'active' : ''}`}
33 onClick={() => activateTab(index)}
34 >
35 {tab.label}
36 </button>
37 ))}
38 </div>
39
40 <div className="tab-content">
41 {activeTab === 0 && (
42 <div className="overview-tab">
43 <h3>Mission Overview</h3>
44 <p>The Apollo 11 mission was the first crewed mission to the Moon...</p>
45 </div>
46 )}
47
48 {activeTab === 1 && (
49 <div className="crew-tab">
50 <h3>Crew</h3>
51 <ul>
52 <li>Neil Armstrong - Commander</li>
53 <li>Edwin "Buzz" Aldrin - Lunar Module Pilot</li>
54 <li>Michael Collins - Command Module Pilot</li>
55 </ul>
56 </div>
57 )}
58
59 {activeTab === 2 && (
60 <div className="timeline-tab">
61 <h3>Timeline</h3>
62 <div className="timeline">
63 <div className="timeline-event">
64 <span className="date">July 16, 1969</span>
65 <span className="description">Launch from Cape Kennedy</span>
66 </div>
67 <div className="timeline-event">
68 <span className="date">July 20, 1969</span>
69 <span className="description">Moon landing</span>
70 </div>
71 <div className="timeline-event">
72 <span className="date">July 21, 1969</span>
73 <span className="description">First step on the Moon</span>
74 </div>
75 <div className="timeline-event">
76 <span className="date">July 24, 1969</span>
77 <span className="description">Return to Earth</span>
78 </div>
79 </div>
80 </div>
81 )}
82
83 {activeTab === 3 && (
84 <div className="systems-tab">
85 <h3>Ship Systems</h3>
86 <p>Command Module: Columbia</p>
87 <p>Lunar Module: Eagle</p>
88 <p>Launch Vehicle: Saturn V</p>
89 </div>
90 )}
91 </div>
92 </div>
93 );
94}Memoization helps avoid unnecessary renders by remembering the results of expensive computations.
1// Component memoization
2const MemoizedTelemetryChart = React.memo(function TelemetryChart({ data }) {
3 // Simulation of expensive computations
4 const processedData = useMemo(() => {
5 console.log('Processing telemetry data...');
6
7 // Expensive data processing
8 return data.map(point => ({
9 x: new Date(point.timestamp).toLocaleTimeString(),
10 y: calculateAverage(point.readings),
11 anomaly: detectAnomaly(point.readings)
12 }));
13 }, [data]); // Recalculate only when data changes
14
15 return (
16 <div className="telemetry-chart">
17 <h3>Telemetry Chart</h3>
18 <div className="chart-container">
19 {/* Chart with processed data */}
20 {processedData.map((point, index) => (
21 <div
22 key={index}
23 className={`data-point ${point.anomaly ? 'anomaly' : ''}`}
24 style={{
25 height: `${point.y * 2}px`,
26 backgroundColor: point.anomaly ? 'red' : 'blue'
27 }}
28 title={`${point.x}: ${point.y} ${point.anomaly ? '(anomaly)' : ''}`}
29 />
30 ))}
31 </div>
32 </div>
33 );
34}, (prevProps, nextProps) => {
35 // Custom props comparison logic
36 if (prevProps.data.length !== nextProps.data.length) {
37 return false; // re-render if data size changed
38 }
39
40 // Compare only the last 5 data points
41 const prevLastFive = prevProps.data.slice(-5);
42 const nextLastFive = nextProps.data.slice(-5);
43
44 for (let i = 0; i < 5; i++) {
45 if (!prevLastFive[i] || !nextLastFive[i]) continue;
46
47 if (
48 prevLastFive[i].timestamp !== nextLastFive[i].timestamp ||
49 !arraysEqual(prevLastFive[i].readings, nextLastFive[i].readings)
50 ) {
51 return false; // re-render if data differs
52 }
53 }
54
55 return true; // don't re-render
56});
57
58// Helper functions
59function calculateAverage(readings) {
60 return readings.reduce((sum, val) => sum + val, 0) / readings.length;
61}
62
63function detectAnomaly(readings) {
64 const avg = calculateAverage(readings);
65 const threshold = avg * 1.5;
66 return readings.some(val => val > threshold);
67}
68
69function arraysEqual(a, b) {
70 if (a.length !== b.length) return false;
71 for (let i = 0; i < a.length; i++) {
72 if (a[i] !== b[i]) return false;
73 }
74 return true;
75}For large data lists, virtualization allows rendering only the elements that are currently visible on screen.
1// Simple virtualization implementation (in real applications
2// it's worth using libraries like react-window or react-virtualized)
3function VirtualizedAsteroidList({ asteroids, rowHeight = 50, visibleRows = 10 }) {
4 const [scrollTop, setScrollTop] = useState(0);
5 const containerRef = useRef();
6
7 const totalHeight = asteroids.length * rowHeight;
8 const startIndex = Math.floor(scrollTop / rowHeight);
9 const endIndex = Math.min(
10 startIndex + visibleRows + 1,
11 asteroids.length
12 );
13
14 const visibleAsteroids = useMemo(() => {
15 return asteroids.slice(startIndex, endIndex);
16 }, [asteroids, startIndex, endIndex]);
17
18 const handleScroll = useCallback(() => {
19 if (containerRef.current) {
20 setScrollTop(containerRef.current.scrollTop);
21 }
22 }, []);
23
24 return (
25 <div className="asteroids-list">
26 <h2>Asteroid Catalog</h2>
27 <p>Number of asteroids: {asteroids.length}</p>
28
29 <div
30 ref={containerRef}
31 className="virtual-list-container"
32 style={{ height: rowHeight * visibleRows, overflow: 'auto' }}
33 onScroll={handleScroll}
34 >
35 <div
36 className="total-height"
37 style={{ height: totalHeight }}
38 >
39 <div
40 className="visible-items"
41 style={{
42 transform: `translateY(${startIndex * rowHeight}px)`
43 }}
44 >
45 {visibleAsteroids.map(asteroid => (
46 <div
47 key={asteroid.id}
48 className="asteroid-item"
49 style={{ height: rowHeight }}
50 >
51 <span className="name">{asteroid.name}</span>
52 <span className="diameter">Diameter: {asteroid.diameter} km</span>
53 <span className="distance">
54 Distance: {asteroid.distance} million km
55 </span>
56 <span
57 className={`hazard-level ${asteroid.hazardLevel}`}
58 >
59 {formatHazardLevel(asteroid.hazardLevel)}
60 </span>
61 </div>
62 ))}
63 </div>
64 </div>
65 </div>
66 </div>
67 );
68}
69
70function formatHazardLevel(level) {
71 switch (level) {
72 case 'high': return 'High threat';
73 case 'medium': return 'Medium threat';
74 case 'low': return 'Low threat';
75 default: return 'No threat';
76 }
77}Lazy loading of components allows deferring the loading of parts of the application until they are needed, which can significantly speed up the initial load of the application.
1// Lazy loading components
2const LazyMarsExplorer = lazy(() => import('./MarsExplorer'));
3const LazyJupiterMoons = lazy(() => import('./JupiterMoons'));
4const LazySaturnRings = lazy(() => import('./SaturnRings'));
5
6function SolarSystemExplorer() {
7 const [activeSection, setActiveSection] = useState(null);
8
9 return (
10 <div className="solar-system-explorer">
11 <h1>Solar System Exploration</h1>
12
13 <div className="planet-selector">
14 <button onClick={() => setActiveSection('mars')}>
15 Mars Exploration
16 </button>
17 <button onClick={() => setActiveSection('jupiter')}>
18 Jupiter's Moons
19 </button>
20 <button onClick={() => setActiveSection('saturn')}>
21 Saturn's Rings
22 </button>
23 </div>
24
25 <Suspense fallback={<div className="loading">Loading exploration module...</div>}>
26 {activeSection === 'mars' && <LazyMarsExplorer />}
27 {activeSection === 'jupiter' && <LazyJupiterMoons />}
28 {activeSection === 'saturn' && <LazySaturnRings />}
29 </Suspense>
30 </div>
31 );
32}Design patterns in React provide proven solutions for common programming problems. They allow you to create code that is:
On our cosmic journey through React, these patterns are like proven interstellar routes that allow you to reach your destination faster and more safely. Experiment with different patterns and choose those that best fit the specific needs of your application.