Clément CREUSAT
Clément CREUSAT

Reputation: 321

How to get objects in array of object in React Native

I'm kind of lost to access some info in my static data. Here's the data :

{
 "info1": {
    "label": "label",
    "class": "class-css",
    "title": "title",
    "text": "text",
    "number": "20",
    "tags": [
         {
            "name": "#twitter"
        },
        {
            "name": "#myspace"
        }
    ]
 },
 "info2": {
    "label": "label",
    "class": "class-css",
    "title": "title",
    "text": "text",
    "number": "20",
    "tags": [
         {
            "name": "#instagram"
        },
        {
            "name": "#facebook"
        }
    ]
  }
}

Then I get the first info like that :

this.setState({
    currentLabel: this.state.labels["info1"]
})

This is why I want and then I want to display info in a component and it's working until I try to get tags information. I tried a .map() but without success and error.

<View>
   <Text>{infoDetail.title}</Text>
   <Text>{infoDetail.text}</Text>
   <Text>How do I get "tags" information</Text>
</View>

Is it possible to access these objects in the array "tags" ?

Upvotes: 2

Views: 24133

Answers (5)

Hemadri Dasari
Hemadri Dasari

Reputation: 33994

yes you can call tags as follows infoDetail.tags and do map on it

render(){
      const tagItems = infoDetail && infoDetail.tags.map((item, index) => {
          return <Text key={index}>{item.name}</Text>
      });
      return(
        <View>
          <Text>{infoDetail.title}</Text>
          <Text>{infoDetail.text}</Text>
          {tagItems}
        </View>
      )
}

Upvotes: 4

devserkan
devserkan

Reputation: 17608

Here is a full working code. Since your labels state property is an object, you need to map it somehow. I've chosen Object.values here. You can use Object.keys or even Object.entries according to your needs.

I've used a separate Info component and passed the values to it, then render there. In this component, we are again mapping the tags, then rendering the list.

class App extends React.Component {
  state = {
    labels: {
      info1: {
        label: "label1",
        class: "class-css",
        title: "title",
        text: "text",
        number: "20",
        tags: [
          {
            name: "#twitter",
          },
          {
            name: "#myspace",
          },
        ],
      },
      info2: {
        label: "label2",
        class: "class-css",
        title: "title",
        text: "text",
        number: "20",
        tags: [
          {
            name: "#instagram",
          },
          {
            name: "#facebook",
          },
        ],
      },
    },
  }

  render() {
    const { labels } = this.state;
    return (
      <div>
        {
          Object.values( labels ).map( value =>
            <Info label={value} key={value.label} /> )
        }
      </div>
    );
  }
}

const Info = ( props ) => {
  const { title, text, tags } = props.label;
  const tagList = tags.map( tag => <p key={tag.name}>{tag.name}</p> );
  return (
    <div style={{ border: "1px solid gray", marginTop: "-1px" }}>
      <p>{title}</p>
      <p>{text}</p>
      <div>{tagList}</div>
    </div>
  );
};

ReactDOM.render(
  <App />,
  document.getElementById("root")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>

Update

If your data is totally static then @Xavi A.'s method is a good option. I don't know how is your list but I provide a simple code including something like you want here.

const labels = {
  info1: {
    label: "label1",
    class: "class-css",
    title: "title",
    text: "text",
    number: "20",
    tags: [
      {
        name: "#twitter"
      },
      {
        name: "#myspace"
      }
    ]
  },
  info2: {
    label: "label2",
    class: "class-css",
    title: "title",
    text: "text",
    number: "20",
    tags: [
      {
        name: "#instagram"
      },
      {
        name: "#facebook"
      }
    ]
  }
};

class App extends React.Component {
  state = {
    currentLabel: Object.keys(labels)[0]
  };

  handleInfoChange = info => this.setState({ currentLabel: info });

  renderList = () => (
    <ul>
      {Object.keys(labels).map(info => (
        <Item key={info} info={info} onClick={this.handleInfoChange} />
      ))}
    </ul>
  );

  render() {
    const { currentLabel } = this.state;
    return (
      <div>
        {this.renderList()}
        <Info currentLabel={currentLabel} />
      </div>
    );
  }
}

const Item = props => {
  const { info, onClick } = props;
  const handleClick = () => onClick(info);
  return <li onClick={handleClick}>{info}</li>;
};

const Info = props => {
  const { currentLabel } = props;
  const { title, text, tags } = labels[currentLabel];
  const tagList = tags.map(tag => <p key={tag.name}>{tag.name}</p>);
  return (
    <div style={{ border: "1px solid gray", marginTop: "-1px" }}>
      <p>{title}</p>
      <p>{text}</p>
      <div>{tagList}</div>
    </div>
  );
};

ReactDOM.render( <App />, document.getElementById( "root" ) );
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>

Upvotes: 3

Xavi A.
Xavi A.

Reputation: 825

No need to save all the static data in your state, you can keep your state cleaner by just saving the selected label:

onLabelSelect = label => {
    //label will be "info1" for example
    this.setState({
        currentLabel: label 
    })
}

Then in your render:

render(){ 
    //get infoDetail from staticData 
    const infoDetail = staticData[this.state.currentLabel]         
    return (
        <View>
            <Text>{infoDetail.title}</Text>
            <Text>{infoDetail.text}</Text>
            {infoDetail.tags.map( ({name}) => <Text>name</Text>)}
        </View>
    )
}

Note about the map. This:

{infoDetail.tags.map( ({name}) => <Text>name</Text>)}

is a shorter version of:

{infoDetail.tags.map( item => {
    return <Text>item.name</Text>
})}

Upvotes: 2

Emad Emami
Emad Emami

Reputation: 6629

You can try Object.keys() and Array.prototype.reduce() to get your favorite data:

const data = {
 "info1": {
    "label": "label",
    "class": "class-css",
    "title": "title",
    "text": "text",
    "number": "20",
    "tags": [
         {
            "name": "#twitter"
        },
        {
            "name": "#myspace"
        }
    ]
 },
 "info2": {
    "label": "label",
    "class": "class-css",
    "title": "title",
    "text": "text",
    "number": "20",
    "tags": [
         {
            "name": "#instagram"
        },
        {
            "name": "#facebook"
        }
    ]
  }
};

const tags = Object.keys(data).reduce((result, key) => {
  return result.concat(data[key].tags);
}, [])

console.log(tags);

/* tags = [
  {
    "name": "#twitter"
  },
  {
    "name": "#myspace"
  },
  {
    "name": "#instagram"
  },
  {
    "name": "#facebook"
  }
] */

Upvotes: 2

Leonardo Alves
Leonardo Alves

Reputation: 63

Probably something like this. <Text>{infoDetail.tags.map(tag => {/*render */})}</Text>

Upvotes: 3

Related Questions