Назначение объектов в JavaScript - PullRequest
0 голосов
/ 21 декабря 2018

Существует объект product, у которого в качестве поля находится объект manufacturer.После получения manufacturers с моего сервера я переназначаю поле продукта manufacturer новыми данными (например, у выбранного производителя есть дополнительный объект avatar в качестве поля).

async componentDidMount() {
  strapi.setToken(this.state.user.jwt);
  const products = await strapi.getEntries('products');
  products.forEach(async product => {
    const manufacturer = await strapi.getEntry('manufacturers', product.manufacturer.id); //fetched manufacturers has additional field "avatar"
    Object.assign(product.manufacturer, manufacturer);
  });

  console.log(products); // product.manufacturer.avatar is not null

  this.setState({
    products
  });

Затем япри попытке отобразить аватар в React render ().

render() {
    if (!this.state.products) return null;
    return(
        {this.state.products ? this.state.products.map(product => (
            // and it says that avatar is null 
            <img src={product.manufacturer.avatar.url} />

            // displays manufacturer with avatar object
            {console.log(product.manufacturer)}
            // says null! 
            {console.log(product.manufacturer.avatar)}
        ))}
    )
}

Также, когда я проверяю состояние с помощью инструментов разработчика React, поле продукта manufacturer имеет объект avatar и не является нулевым.

ОБНОВЛЕНИЕ : Спасибо Сергею Суслову

strapi.setToken(user.jwt);
      const fetchedProducts = await strapi.getEntries('products');
      const promices = fetchedProducts.map(async fetchedProduct => {
        const manufacturer = await strapi.getEntry('manufacturers', fetchedProduct.manufacturer.id);
        const product = { ...fetchedProduct, manufacturer };

        return product;
      });

      Promise.all(promices).then(products =>
        this.setState({
          products
        })
      );

Ответы [ 2 ]

0 голосов
/ 21 декабря 2018

Вы присваиваете с помощью метода assign, который не изменяет исходный объект, он возвращает новый объект в результате, отметьте это https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign. Вам нужно сделать что-то вроде этого: product = {... product, производитель: ваш статус назначения} Основная причина в том, что ваша функция обратного вызова в foreach является асинхронной, js не ожидает завершения всех вызовов функции foreach, она продолжает выполняться, вызывает асинхронное слово, пытается использовать для этого Promise или лучше использоватьдействия для асинхронных запросов, спасибо библиотекарю или сагам.

0 голосов
/ 21 декабря 2018

Это потому, что при первом рендере у вас нет значения avatar.Эти значения выбираются после первого рендера (componentDidMount).

Вам необходимо добавить тест, чтобы учесть этот первый рендер.

Кроме того, причина, по которой ваш console.log не соответствует, заключается в том, что вы перезаписываете значение продукта, чтобычтобы быть более неизменным, вы должны .map вместо forEach и вернуть копию вашего продукта вместо изменения существующего.

Как бы я написал:

constructor(props){
    super(props);

    this.state = {
        products: []
    }
}

render() {
    return this.state.products.map(product => {
        const {
            avatar = {}
        } = product.manufacturer;
        return (
            <img src={avatar.url} />
        );
    });
}
...