3

I am trying to give a key prop to my Tag component, but I can't seem to give the right ID to my Tag component.

First, I am making a call to this (single image) endpoint:

componentDidMount() {
    fetch(`//derpibooru.org/${this.props.match.params.id}.json`)
        .then(res => res.json())
        .then(data => this.setState({ singleImage: data }))
}

which serves this json file here (for example). Here is an example image:

enter image description here

I then want to insert that ID inside of this Tag component in order to suppress the key prop warning from React.

        const tagList = this.state.singleImage.tags.split(', ').map( tag => {
                return (
                    <Link to={`/tags/${tag}`}>
                        <Tag key={???} tag={tag} />
                    </Link>
                )
            }
        )

However, here's the problem. I'm mapping over [...].singleImage.tags which are the tag slugs, but I don't receive the IDs. In the API, there is an endpoint of //derpibooru.org/tags/{some_tag}.json and at this (tags) endpoint, I can get the ID with tag.id and I attempted another fetch (inside of map) like this:

        const tagList = this.state.singleImage.tags.split(', ').map( tag => {
                fetch(`//derpibooru.org/tags/${tag}.json`)
                .then(res => res.json())
                .then(data => {
                  return (
                    <Link to={`/tags/${tag}`}>
                        <Tag key={data.tag.id} tag={tag} />
                    </Link>
                  )
                }
            }
        )

but then in this case, the map does not return.

I feel like this is the wrong approach since the single image endpoint has the tag_ids, but I just don't know how to put them inside my Tag component.

Thanks for any help.

peterh
  • 11,875
  • 18
  • 85
  • 108
Student22
  • 1,979
  • 5
  • 22
  • 33
  • 1
    Are the slugs unique? If so they are fine to use. Otherwise, if the slug order is always the same, you could just use the index in the array – Matthew Herbst Jan 05 '19 at 08:39

2 Answers2

1

Because fetch(//derpibooru.org/tags/${tag}.json) it's async operation, and map work only with sync operations;

you can iterate your cycle inside for which inside async await function:

async function printFiles() {
    for (const tag of tags) {
        const res = await fetch(`//derpibooru.org/tags/${tag}.json`);
        console.log(res);
    }
}

Using async/await with a forEach loop

Vadim Hulevich
  • 1,803
  • 8
  • 17
  • this is another good way to solve the problem with the tags endpoint, but I thought i could save the trouble from fetching again and using the `tag_ids` somehow just like Hemadri's answer. i'll consider this for the future. thank you Vadim. – Student22 Jan 05 '19 at 08:58
1

In this case use index as key like

  const tagList = this.state.singleImage.tags.split(', ').map( (tag, index) => {
            return (
                <Link to={`/tags/${tag}`}>
                    <Tag key={'Key-'+index} tag={tag} />
                </Link>
            )
        }
    )
Hemadri Dasari
  • 32,666
  • 37
  • 119
  • 162
  • 1
    oh I had no idea you could use index like that in a map. that would have saved me a bunch of time! really good to know. i adopted your answer and saved the `tag_ids` in a state array and then used index to iterate through them like this ``. thanks for your answer i really appreciate it! – Student22 Jan 05 '19 at 08:56
  • You are welcome :) index as a key is always second choice meaning when the data doesn’t have unique ids then we will depend on index for uniqueness like I mentioned in my answer. For more details take a look at this thread https://stackoverflow.com/questions/52176673/most-efficient-way-of-rendering-jsx-elements-when-iterating-on-array-of-data-in – Hemadri Dasari Jan 05 '19 at 09:02