When building apps, you often encounter situations where you need to render different components or layouts based on data. Instead of using a lot of if-else or switch statements, you can use a configuration-driven approach for cleaner and more scalable code.
Example: Dynamic Rendering with a Component Map
Let’s dynamically render different input fields based on a configuration object.
import React from "react";
// Components for different input types
const TextInput = ({ label, name, value, onChange }) => (
<div>
<label>{label}:</label>
<input
type="text"
name={name}
value={value}
onChange={onChange}
/>
</div>
);
const NumberInput = ({ label, name, value, onChange }) => (
<div>
<label>{label}:</label>
<input
type="number"
name={name}
value={value}
onChange={onChange}
/>
</div>
);
const Checkbox = ({ label, name, checked, onChange }) => (
<div>
<label>
<input
type="checkbox"
name={name}
checked={checked}
onChange={onChange}
/>
{label}
</label>
</div>
);
// Component map for dynamic rendering
const componentMap = {
text: TextInput,
number: NumberInput,
checkbox: Checkbox,
};
// Configuration object for form fields
const formConfig = [
{ type: "text", label: "Name", name: "name" },
{ type: "number", label: "Age", name: "age" },
{ type: "checkbox", label: "Subscribe to Newsletter", name: "subscribe" },
];
const DynamicForm = () => {
const [formData, setFormData] = React.useState({
name: "",
age: "",
subscribe: false,
});
const handleChange = (e) => {
const { name, value, type, checked } = e.target;
setFormData((prev) => ({
...prev,
[name]: type === "checkbox" ? checked : value,
}));
};
return (
<form>
{formConfig.map((field) => {
const Component = componentMap[field.type];
return (
<Component
key={field.name}
label={field.label}
name={field.name}
value={formData[field.name]}
checked={formData[field.name]}
onChange={handleChange}
/>
);
})}
<button type="submit">Submit</button>
</form>
);
};
export default DynamicForm;
How It Works
1. Component Map:
A mapping (componentMap) links input types (e.g., "text", "checkbox") to specific React components.
2. Configuration Object:
The formConfig array defines the structure of the form, including each field’s type, label, and name.
3. Dynamic Rendering:
The formConfig array is iterated over, and the appropriate component is rendered dynamically based on the field type.
4. Single State Object:
Form state (formData) is managed in a single object, updated dynamically based on input changes.
Benefits
Scalability: Easily add new field types or forms by extending the formConfig and componentMap without changing the core logic.
Reusability: The components and configuration can be reused across multiple forms.
Readability: Eliminates repetitive JSX and if-else logic, making the code more concise.
When to Use This
When you need to dynamically render components (e.g., forms, modals, or dashboards).
When your app has repetitive but configurable UI patterns.
When you want a cleaner, more modular architecture.
This technique is a game-changer for building flexible and reusable UI components in React! Let me know how you’d use this in your project!