2

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" ?

2
  • Can you please share the code that you have tried with .map, I tried your JSON with .map and it worked just fine. Commented Sep 19, 2018 at 16:04
  • If I tried this and I have "undefined" : const tagsItems = this.state.currentLabel.tags.map((tag, index) => { return <Text key={index}>{tag.name}</Text> }) If I do it like this, it's working : const tagsItems = this.state.labels["r1"].tags.map((tag, index) => { return <Text key={index}>{tag.name}</Text> }) Commented Sep 19, 2018 at 19:32

5 Answers 5

4

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>
      )
}
Sign up to request clarification or add additional context in comments.

2 Comments

The fact is I'm using a Functional (Stateless) Component so I pass my props: <LabelDetail infoDetail={this.state.currentLabel} /> then I use infoDetail to display every info.. but map() doesn't work
First you need to check whether infoDetail really has data or not and then only do map on it. Since you shared only pieces of code I just advised you about how you can do map on it and display. So you need to do conditional check because doing map. I Updated my answer please have a look you will understand
3

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>

7 Comments

It works but it displays all the data and not only the first one (the current/selected label) but thank you it's a good example that I can follow !!
You are welcome. So, is there a list you can select? Something can be written according to this case of course.
the case is : I have this list with "info1, info2, ... and more". I want the first item selected and then I will manipulate the state with a onPress on several elements to switch between info1 or info4, or info5 ... currentLabel will change ;-)
Ok, is your data totally static or do you get it from somewhere else asynchronously?
You are welcome. If anything is blurry, don't hesitate to ask here. I can explain a little bit more. If you are new I strongly advise React's official documentation. For other things like map, Object.keys let MDN be your friend, a close one :)
|
3

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

Comments

2

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"
  }
] */

Comments

2

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>
})}

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.