Props Without Pain: Props Collection / Getter Pattern
Provide helper functions (getInputProps) that spread required props onto elements. This keeps your component flexible while hiding complexity. Perfect for libraries like Downshift that need rich APIs.
- Technology
- 3 min read
Ever been at a restaurant where the waiter brings out all condiments in one tray instead of making you ask for salt, pepper, ketchup, and chili separately?
That’s exactly what the Props Collection / Getter Pattern does in React — it bundles all the props you need into one neat package, so you don’t have to manually manage each piece every time.
Core Idea
The Props Collection Pattern provides a single object or function (getter) that returns all the props you need for a component.
👉 Instead of:
<input onChange={handleChange} value={value} aria-label="username" />
You get:
<input {...getInputProps()} />
Basics & Need
- When building reusable components (inputs, buttons, modals), consumers often need lots of props.
- Passing them one by one is error-prone and verbose.
- The Props Getter pattern provides a preconfigured props object (often via a function) that consumers can spread onto their components.
How to Achieve It
Example 1: Basic Props Getter
const useInput = () => { const [value, setValue] = React.useState(""); const getInputProps = (props = {}) => ({
value, onChange: (e) => setValue(e.target.value), ...props, // allow overrides
}); return { value, getInputProps };
};// Usageconst UsernameField = () => { const { value, getInputProps } = useInput(); return ( <> <input {...getInputProps({ placeholder: "Enter username" })} /> <p>Value: {value}</p> </>
);
};
👉 getInputProps ensures the consumer gets all required props, while still allowing customization.
Example 2: Multiple Props Collections (Input + Button)
const useToggle = () => { const [on, setOn] = React.useState(false); const getToggleProps = (props = {}) => ({ "aria-pressed": on, onClick: () => setOn(!on),
...props,
}); return { on, getToggleProps };
};// Usageconst Toggle = () => { const { on, getToggleProps } = useToggle(); return ( <> <button {...getToggleProps()}>{on ? "ON" : "OFF"}</button> </>
);
};
Best Practices
✅ Use getters to bundle required behavior (like onChange, value).
✅ Allow consumers to override or extend props.
✅ Keep function naming clear (getInputProps, getToggleProps).
❌ Don’t overstuff getters with too many unrelated props.
Real-World Examples
- Forms (Formik, React Hook Form) → Inputs come pre-bundled with handlers and values.
- Toggle Switches → Provides accessibility props + event handlers.
- UI Libraries (Downshift, Headless UI) → Consumers spread getters for inputs, menus, buttons.
Advantages
✔ Cleaner API for consumers.
✔ Reduces prop drilling and mistakes.
✔ Supports overrides and extensions.
✔ Enhances accessibility by including ARIA props.
Disadvantages
⚠ May hide complexity from beginners.
⚠ Debugging is harder when props come from a single getter.
⚠ Overuse can lead to unintuitive APIs.
Common Problems / Pitfalls
- Forgetting to spread props (
{...getInputProps()}) → component breaks. - Overwriting internal props (like
onChange) without merging. - Poorly documented getters confuse consumers.
Summary Recommendation
🎯 Use the Props Getter Pattern to simplify component APIs by bundling required props into a getter function. Perfect for forms, toggles, dropdowns, and UI libraries where components need multiple props consistently. Keep APIs clean, flexible, and override-friendly.