React mapping - Giving key prop when mapping over slug names

Viewed 258

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.

2 Answers

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

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