Weijing Jay Lin
Weijing Jay Lin

Reputation: 3238

Is there a better/another way to create list in react?

In React, to render a list you generally map over and render elements like this:

list.map((itm, idx) => <li>{itm}</li>)

Can I refactor this to a component that is generic enough to handle different element types but still do the mapping for me? Aka,

<EasyList data={list} /> // tag would be "li" by default
<EasyList data={list} tag="p" /> // a customized tag name

What would be the best way to implement something like this?

Upvotes: 1

Views: 71

Answers (2)

Ryan Cogswell
Ryan Cogswell

Reputation: 81006

This answer isn't much different than John Ruddell's, but I had already completed it before seeing his.

You can make this EasyList component as sophisticated as you need it to be. My example below shows that you can have it control the parent component (ul by default) and that the component types passed can be html element types (e.g. ul, li, p) or custom components such as DivWithHeaderText in my example.

import React from "react";
import ReactDOM from "react-dom";

const EasyList = ({ data, ListComponent = "ul", ItemComponent = "li" }) => {
  return (
    <ListComponent>
      {data.map(item => (
        <ItemComponent>{item}</ItemComponent>
      ))}
    </ListComponent>
  );
};
const myItems = ["Here", "are", "my", "list", "items"];
const DivWithHeaderText = ({ children }) => {
  return (
    <div style={{ border: "solid black 1px" }}>
      <div>Here is my header</div>
      <hr />
      {children}
    </div>
  );
};
function App() {
  return (
    <>
      <EasyList data={myItems} />
      <EasyList
        data={myItems}
        ListComponent={DivWithHeaderText}
        ItemComponent="p"
      />
    </>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

Edit EasyList

Upvotes: 0

John Ruddell
John Ruddell

Reputation: 25842

You can achieve exactly what you are describing in the way you are describing it. The implementation of EasyList could look something like this

const EasyList = ({data, tag: Elem = 'li'}) => {
  return data.map( (item, idx) => <Elem key={idx}>{item}</Elem>) 
}

and usage would look like

<EasyList data={list} /> // tag would be "li" by default
<EasyList data={list} tag="p" /> // a customized tag name

Demo to play with


There are multiple ways you could implement this, so depending on needs you could go the route of a render prop, where you define the exact elements you need. Really it depends on what kind of control / granularity you want.

<EasyList data={seed} render={ (item, idx) => <li>{item}</li>} />

and the implementation with a render prop would look like

const EasyList = ({data, render}) => {
  return data.map(render) 
}

Upvotes: 2

Related Questions