I'm quite new to React and I don't know if there is a pattern to reduce duplicated code. I'm aware of higher order components but I'm not sure how/if they can help me. Here is the issue that I'm having:
Here is the scenario:
I have three React components in my app: Studios, Projects, Actors
Each component corresponds to a route on the front-end:
ProjectsStudiosActorsEach component does pretty much the same thing, looping through the items and render a component:
Projects: loop through the data for projects and render a Project component for each project
Studios: loop through the data for studios and render a Studio component for each studio
Actors: loop through the data for actors and render an Actor component for each actor
Now the model for a Project, Studio, and Actor are pretty much the same with slight variation:
Studio: image, name, detailsActor: image, name, and bioProject:image, title, and descriptionAlso, on the "List" view, when I click on an item, it takes me to the details of that item. For example, when I am on the /projects view when I click on a project item, it takes me to /projects/:id and renders the ProjectDetail component. So by now for each entity I have three components: ItemList, Item, ItemDetail. Which is total of 3 x 3 = 9 components. I feel like there is a better way of doing this. Maybe I don't understand the responsibility of the router? Right now, I have a route for the ItemList and ItemDetail for every entity:
ProjectsProjectDetailActorsActorDetailStudiosStudioDetailEventually I would like to generalize models that are very similar to each other to reduce boilerplate code. Possibly:
ItemList: would take data as an input and render the appropriate Item component.Item: The component that would show up on the ItemListItemDetail: The component that shows the details of the Itemand a generic client route rule that can automatically map the route to the appropriate component.
I'm going to refer to components vs instances in my answer; check out this article for an explanation of the differences, or read this TL;DR: a component is the class or function that specifies the behavior of a JSX tag, while an instance is typically represented by JSX in a render method. So function Foo() { return <div />;} would be a component, while <Foo /> would be an instance.
The magic of JSX is that tag names are simply variables. For instance, when you type <div />, the tag name is simply referring to a div variable defined by React core. Assuming you've imported a component Foo, when you type <Foo /> then the tag name is referring to the variable you've brought in scope by importing.
You could use a higher-order component that takes a React component, and then use that component in the render method. For example (disclaimer, I'm writing this on-the-fly and it may contain errors):
// Assume the variables `studios, actors, projects` are arrays
// of their respective item types, and `StudioDetail, ActorDetail,
// ProjectDetail` are the customized views you've described in
// your question.
class ItemList extends React.Component {
render() {
const View = this.props.view;
const items = this.props.items;
return (<div>
{items.map((item, i) => <View key={i} item={item} />}
</div>);
}
}
class App extends React.Component {
render() {
return (<div>
<ItemList view={StudioDetail} items={studios} />
<ItemList view={ActorDetail} items={actors} />
<ItemList view={ProjectDetail} items={projects} />
</div>);
}
}
Just make sure that whatever you pass into the view prop is a component matching the type of item you're showing, and you ought to be off to a good start.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With