Noticed a React anti-pattern while mentoring a younger front-end developer on our project.
Imagine you have a component that represents a list of articles. At one point, you realize that each article in the list is too complex:
const ArticleList = (props) => {
return <div class="articles">
<ul class="article-list">
{ props.articles.map(article =>
<li class="article">
<h2 class="article__title">{ article.title }</h2>
{ /* 25 other tags */ }
</li>
) }
</ul>
{ /* ... */ }
</div>;
}
So you decide to move the item to a separate component. You take that code inside map(), extract it into <Article> and get something like this:
const Article = (props) => {
return <li class="article">
<h2 class="article__title">{ props.title }</h2>
{ /* 25 other tags */ }
</li>;
}
const ArticleList = (props) => {
return <div class="articles">
<ul class="article-list">
{ props.articles.map(article =>
<Article title={article.title} { /* other props */ } />
) }
</ul>
{ /* ... */ }
</div>;
}
Don’t do it this way. This approach is wrong. The problem is that by taking a <li> and making it a root of the component, you’ve just made your component non-reusable. This means that if you’d like to reuse <Article> in another place, you’ll only be able to apply it somewhere inside a list – because of this <li>. If you decide to render <Article> into e.g. a <div>, not only will this be non-semantic (<li> can only appear inside of <ul>s), but will also add unnecessary list item styling which is super weird.
Solution#
The solution is simple: move the <li> back into the <ArticleList> component and make the <Article>’s root element a <div> or something else. This will probably require some refactoring in your styles, but will make the component reusable. Look how cool:
const Article = (props) => {
// Notice: <li>s are gone
return <div class="article">
<h2 class="article__title">{ props.title }</h2>
{ /* ... */ }
</div>;
}
const ArticleList = (props) => {
return <div class="articles">
<ul class="article-list">
{ props.articles.map(article =>
<li class="article-list__item">
<Article title={article.title} { /* other props */ } />
</li>
) }
</ul>
{ /* ... */ }
</div>;
}
// And now you can easily render an article inside of a sidebar – have no idea why though
const Sidebar = (props) => {
return <div class="sidebar">
<div class="sidebar__article">
<Article title="Look ma" { /* other props */ } />
</div>
{ /* ... */ }
</div>;
}
Hi you have a wonderful Posting site It was very easy to post good job