Search code examples
arraysreactjsobjectreact-propsarray.prototype.map

What is the right way to pass nested objects in object array in React?


In my map function below I am trying to access the nested objects in my data. I would like to say that "If an object in my SlideData has the property "list", display it". I am passing props from the data to my TextSlide component, but there must be a better way than passing a ton of props to the TextComponent?

function Slideshow(props) {

//MY DATA
const SlideData = [{
{
    title: "The Title",
    text1: "Monkey",
    text2: "D",
    text3: "Luffy",
    list: [
            {
              listTitle: "The List",
              listItem1: "Zoro",
              listItem2: "Nami",
              listItem3: "Sanji",
              listItem4: "Ussop",
              listItem5: "Chopper",
              listItem6: "Franky",
            },
          ],
    imagesrc: picture,
    imagewidth: "100px",
  },
}]
//MAP THROUGH DATA (is there a better way to pass multiple props here?? maybe with {...props} ?)

const textSlides = SlideData.map((item),index) => ( <TextSlide
      key={index}
      title={item.title}
      text1={item.text1}
      text2={item.text2}
      listTitle={item.listTitle}
      listItem1={item.listItem1}
      listItem2={item.listItem2}
      listItem3={item.listItem3}
      listItem4={item.listItem4}
      listItem5={item.listItem5}
      listItem6={item.listItem6}
  />));

return (
    <>
        {textSlides}
    </>
  );
}

//TEXTSLIDE COMPONENT//

const TextSlide = (props) => {
  return (
    <>
      <div className="slide">
        <div className="standard-grid">
          <span className="slide-title title">{props.title}</span>
             <div className="content">
               <p>{props.text1}</p>      
               <p>{props.text2}</p>         
               <p>{props.text3}</p>       
               {props.list ? <div>
                <h4>{props.list2}</h4>
                <ul>
                  <li>{props.listItem1}</li>
                  <li>{props.listItem2}</li>
                  <li>{props.listItem3}</li>
                  <li>{props.listItem4}</li>
                  <li>{props.listItem5}</li>
                  <li>{props.listItem6}</li>
                </ul>
              </div> : null} 
             </div>
            {props.imagesrc ? (<img className="picture" src={props.imagesrc} 
            style={{ maxWidth: props.imagewidth }} alt="image" />) : null}
        </div>
      </div>
    </>
  );
};

export default TextSlide;

Solution

  • Since it seems like you've a bit of control over the data structure and format, I would suggest trying to format your data in such a way that lends itself to being easily renderable. In React, lists are commonly converted/stored in arrays so that they can be mapped to JSX.

    Example:

    const SlideData = [
      {
        title: "The Title",
        text: ["Monkey", "D","Luffy", ...];
        list: {
          title: "The List",
          items: [ "Zoro", "Nami", "Sanji", "Ussop", "Chopper", "Franky"],
        },
        image: {
          src: picture,
          width: "100px",
        },
      },
      ...
    ];
    

    Anywhere you were previously using essentially a duplicate "itemX" key is a prime candidate to be stored as an array.

    You can simply pass an entire object property as a prop, and render and pass on any nested properties.

    Example:

    const textSlides = SlideData.map((item, index) => (
      <TextSlide
        key={index}
        {...item}
      />
    ));
    

    Child

    const TextSlide = ({
      title,
      text = [],
      list,
      image,
    }) => {
      return (
        <div className="slide">
          <div className="standard-grid">
            <span className="slide-title title">{title}</span>
            <div className="content">
              {text.map((t, i) => <p key={i}>{t}</p>)}
              {list && (
                <div>
                  <h4>{list.title}</h4>
                  <ul>
                    {list.items.map((item, i) => (
                      <li key={i}>{item}</li>
                    ))}
                  </ul>
                </div>
              )}
            </div>
            {image && (
              <img
                className="picture"
                src={image.src} 
                style={{ maxWidth: image.width }}
                alt="image"
              />
            )}
          </div>
        </div>
      );
    };