pattern for code reusability
Render props is a React pattern where a component receives a function as a prop and calls that function to decide what to render.
Instead of a component returning fixed JSX, it:
examples
// <MealProvider render={...} />
<MealProvider render={data => (
<p>Ingredients: {data.ingredients}</p>
)}/>
// DataProvider({ render })
function DataProvider({ render }) {
const data = "Hello";
return render(data);
}
<DataProvider render={(value) => <h1>{value}</h1>} />
// MouseTracker({ children })
function MouseTracker({ children }) {
const [pos, setPos] = useState({ x: 0, y: 0 });
return (
<div onMouseMove={e => setPos({ x: e.clientX, y: e.clientY })}>
{children(pos)}
</div>
);
}
<MouseTracker>
{(pos) => (
<p>
Mouse position: {pos.x}, {pos.y}
</p>
)}
</MouseTracker>
// Toggle({ children })
function Toggle({ children }) {
const [on, setOn] = useState(false);
return children({
on,
toggle: () => setOn(o => !o),
});
}
<Toggle>
{({ on, toggle }) => (
<button onClick={toggle}>
{on ? "ON" : "OFF"}
</button>
)}
</Toggle>
import "./App.css";
import { useEffect, useState } from "react";
const MousePosition = ({ render }) => {
const [mousePosition, setMousePosition] = useState({
x: 0,
y: 0,
});
useEffect(() => {
const handleMousePositionChange = (e) => {
// Use e.clientX and e.clientY to access the mouse position on the screen
setMousePosition({
x: e.clientX,
y: e.clientY,
});
};
window.addEventListener("mousemove", handleMousePositionChange);
return () => {
window.removeEventListener("mousemove", handleMousePositionChange);
};
}, []);
// What should be returned here?
return render(mousePosition);
};
// This component should not receive any props
const PanelMouseLogger = () => {
return (
<MousePosition
render={(mousePosition) => (
<div className="BasicTracker">
<p>Mouse position:</p>
<div className="Row">
<span>x: {mousePosition.x}</span>
<span>y: {mousePosition.y}</span>
</div>
</div>
)}
/>
);
};
// This component should not receive any props
const PointMouseLogger = () => {
return (
<MousePosition
render={(mousePosition) => (
<p>
({mousePosition.x}, {mousePosition.y})
</p>
)}
/>
);
};
function App() {
return (
<div className="App">
<header className="Header">Little Lemon Restaurant 🍕</header>
<PanelMouseLogger />
<PointMouseLogger />
</div>
);
}
export default App;