1

I'm learning React and ran into an issue with rendering multiple elements.

The issue is that I am retrieving an Array from Firebase which needs to return a new div and svg for each item in the array. I understand React will only render 1 element so I need to put my content inside a wrapper, which I've done. I've also created a variable that uses .map() to loop through the array and create these elements for me.

What I don't understand, is why is it not returning a new div and svg for each item in the array? Instead, its only creating 1 div and svg? The array contains a list of folder names.

Any help would be appreciated.

class SidebarPrivateFolders extends React.Component {
  constructor(props) {
    super(props)
  }

  render() {

    let list = this.props.data.map((currentObj) => {
      return (
        <div>
          <svg className="sidebar-icon">
            <use xlinkHref={currentObj.xlinkHref}></use>
          </svg>
          <div className="public-folders">{currentObj.name}</div>
        </div>
      );
    });

    return (
      <div className="sidebar-section">
        <div className="sidebar-section-wrapper">
          {list}
        </div>
      </div>
    );
  }
}

Console.log(this.props.data) returns the following screenshot.

enter image description here

2
  • can you post a sample data of this.props.data Commented Jun 20, 2016 at 2:24
  • it does.. data is an array with only one element... maybe you want data[0].name[0].map(fn) Commented Jun 20, 2016 at 2:34

2 Answers 2

1

In your output.. currentObj.name is an array.. so you've to loop over it as well if you want div to be created for each element inside name array.

You could do something like:

class SidebarPrivateFolders extends React.Component {
  constructor(props) {
    super(props)
  }

  render() {

    let list = this.props.data.map((currentObj) => {
return currentObj.name[0].map((innerArray,i) => { 
      return (
        <div key={i}>
          <svg className="sidebar-icon">
            <use xlinkHref={currentObj.xlinkHref}></use>
          </svg>
          <div className="public-folders">{currentObj.innerArray[i]}</div>
        </div>
      );
    });
    });

    return (
      <div className="sidebar-section">
        <div className="sidebar-section-wrapper">
          {list}
        </div>
      </div>
    );
   }

P.S This is solution is untested. You might get syntax errors

Sign up to request clarification or add additional context in comments.

3 Comments

as per @azium comment you might want to try currentObj.name[0].map instead of currentObj.name.map refer to edited ans
Edit: I had to change the names to [innerArray] and it's not displaying correctly. Thanks for the help! It makes sense that I had an Array inside an Array and needed to loop through that properly. Original: This answer is sort of working. Progress, but not quite there. It's rendering 9 different divs with a folder icon, however the names of each folder are displaying in the first div.
yep...the [name] should be inner array, as I said in OP trhat it was untested..happy coding!!!
0

EDIT v2: Your Data input is organized interestingly, if you're creating this input from a higher level, it may be efficient to reorganize how it's composed, however, deconstructing the items from the data array makes it easier to call in subsequent functions:

// Take out the name array and xlinkHref from data
let {xlinkHref, name} = this.props.data[0];
let list = name[0].map((name, i) => {
  return (
    <div key={'sidebar_'+i}>
      <svg className="sidebar-icon">
        <use xlinkHref={xlinkHref}></use>
      </svg>
      <div className="public-folders">{name}</div>
    </div>
  );
});

Original Response without Data sample:

A part of React's internal diffing algorithm requires lists of generated objects to be identified with a unique 'key' property. You'll need to add this property to the wrapping Div of each iterator.

So within the Map function, you could track the parameter for the index of the map and use that to keep the keys of your list separate.

There's a good explanation of this here in the Dynamic Children section: https://facebook.github.io/react/docs/multiple-components.html

Here's what your code COULD look like:

class SidebarPrivateFolders extends React.Component {
  constructor(props) {
    super(props)
  }

  render() {

    let list = this.props.data.map((currentObj, i) => {
      return (
        <div key={'sidebarlist_'+i}>
          <svg className="sidebar-icon">
            <use xlinkHref={currentObj.xlinkHref}></use>
          </svg>
          <div className="public-folders">{currentObj.name}</div>
        </div>
      );
    });

    return (
      <div className="sidebar-section">
        <div className="sidebar-section-wrapper">
          {list}
        </div>
      </div>
    );
  }
}

Let me know if this fixes your issue.

2 Comments

Hmm looks like I am getting "cannot read property 0 of undefined"
Oh I misread the Data object, it IS an array. How are you creating this data? I'll edit my post for accuracy, sorry.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.