Как я могу выполнить вызов api в методе map, который отображает узлы dom?

#reactjs #asynchronous #redux #material-ui

#reactjs #асинхронный #сокращение #материал-пользовательский интерфейс

Вопрос:

Я пытаюсь использовать обещание внутри моего метода map, но возврат из обещания показывает [object Promise]. Но в коде, где я дал обещание, я возвращаю response.data.itemThatIWant. Как я могу получить фактические результаты из promise в моем методе map?

Я попытался вызвать promise вне карты и сохранить результаты в массиве, а затем отобразить этот массив внутри map, но затем я получаю дубликаты всего.

Вот код, который пытается вызвать promise в map

 <Grid className={classes.listGrid} container>
                {favoriteProviders.map((provider, index) =>

                  <Grid item lg={6} xs={12} key={index} value={index}>

                    <Paper className={classes.paper}>
                      <Grid container direction="row">
                        <img src={`https://animasds-content.azureedge.net/provider-images/${getImagePath(provider.doc_id)}?${Date.now()}`}
                          alt="doctor" style={{ margin: 5, height: 60, borderRadius: 5 }} />

  

Вот обещание, которое я создал:

 import axios from "axios";

async function getImagePath(id) {
    try {
        const res = await axios.post(`${process.env.REACT_APP_API_URL}/api/provider/image/img`, { id },
            {
                headers: {
                    authorization: `Bearer ${localStorage.getItem("access_token")}`
                }
            })
        return res.data.ImagePath
    } catch (err) {
        console.log(err)
    }
}
export default getImagePath;

  

Если я помещу console.log (res.data.ImagePath) здесь я получаю то, что хочу, но в map я просто получаю [object Promise]

Я ожидаю, что изображение будет отображаться на основе информации из каждого элемента в массиве, который я отображаю.

Ответ №1:

Вам нужно отслеживать состояние этого getImagePath, когда он не готов, вы должны отобразить что-то еще, например

 {this.state.images[imageId] ? <img src={`https://animasds-content.azureedge.net/provider-images/${this.state.images[imageId]}?${Date.now()}`}
                          alt="doctor" style={{ margin: 5, height: 60, borderRadius: 5 }} /> : <Something to indicate not ready />
  

И вы можете обрабатывать состояние готовности, когда получаете результат, например

 async componentDidMount() {
  try {
    const response = await getImagePath(XXXXXX);
    if (!response.ok) {
      throw Error(response.statusText);
    }
    const json = await response.json();
    this.setState({ images: {id: json} });
  } catch (error) {
    console.log(error);
  }
}

  

Ответ №2:

Обычно это было бы <img src={"https://animasds-content.azureedge.net/provider-images/${await getImagePath(provider.doc_id)}?${Date.now()}"}

но я предполагаю, что рендеринг не может быть асинхронным, поэтому вам придется сделать это в каком-либо методе жизненного цикла и, возможно, установить его в состояние.

Поэтому я предлагаю:

 class ApiImg extends Component {

  state = {};

  async componentDidMount() {
    this.setState({ url: await getImagePath(this.props.id)});
  }

  render() { 
    {this.state.url amp;amp;
       <img src={`https://animasds-content.azureedge.net/provider-images/${this.state.url}?${Date.now()}`}
         alt="doctor" style={{ margin: 5, height: 60, borderRadius: 5 }} />
    }
  }
}
  

используя его таким образом:

 <Grid container direction="row">
    <ApiImg id={provider.doc_id} />