React / redux: ошибка рендеринга свойств вложенных объектов - PullRequest
0 голосов
/ 13 июня 2019

У меня есть интерфейс с реакцией / редукцией, который получает данные через RabbitMQ.Когда приходит сообщение, наш обработчик сообщений отправляет действие, например, PRODUCT_DETAILS_LOADED, которое обновляет магазин и отображает соответствующий компонент с информацией о продукте.Это на 95% работает, но если я пытаюсь отобразить свойства вложенного объекта, я получаю сообщение об ошибке: Cannot read property <prop> of undefined.

Я провел некоторые исследования по этому вопросу.Большинство ответов показывают, что имеет место состояние гонки и что компонент пытается отобразить свойства, прежде чем они будут «готовы».Я не понимаю, как это может быть, так как я не делаю вызов REST;У меня уже есть данные из очереди сообщений, и я уже обновил магазин.Более того, console.log внутри функции render покажет правильные значения вложенных свойств.Вот основная часть моего компонента ProductDetails:

const mapStateToProps = state => {
  return { product: state.productDetail };
}

class ProductDetails extends Component {

  render() {
    console.log(this.props.product.availability.forsale);  //This will correctly show 'true' or 'false'
    return (
            <div> 
                <h3>Product Details Page</h3>
                <h5>Details for {this.props.product.name}: </h5>
                <div>
                  Name:  {this.props.product.name}
                  <br/>
                  SKU:  {this.props.product.sku}
                  <br/>
                  Available:  {this.props.product.availability.forsale} //This throws an error
                  <br/> 
                  {/*Price: {this.props.product.price.$numberDecimal} //This would also throw an error
                  <br/>*/}
                  Description: {this.props.product.description}              
                </div>
                <Link to="/">Back to Home Page</Link> 
            </div>
    )
  }
}

const Details = connect(mapStateToProps, null)(ProductDetails);
export default Details;

Вот фрагмент кода из обработчика, который срабатывает при получении сообщения о продукте:

  } else if(json.fields.routingKey === 'product.request.get') {   
    if(json.status === 'success') {
     let payload = json.data;
      store.dispatch(productDetailsLoaded(payload));
    } 

Вот функция, которая отправляет действие:

export function productDetailsLoaded(details) {
  return { type: PRODUCT_DETAILS_LOADED, productDetail: details }
}

И, наконец, редуктор:

  if(action.type === PRODUCT_DETAILS_LOADED) {
    return Object.assign({}, state, {
      productDetail: action.productDetail
    });
  }

Я видел несколько ответов, которые предлагают что-то вроде следующего, чтобы предотвратить ошибку: let av = this.props.product.availability ? this.props.product.availability.forsale : '';.Это не работает для меня.Хотя это предотвращает ошибку, я буду отображать пустое значение.Это не вариант для меня;Я должен показывать правильную информацию на странице с подробностями, а не просто «не неправильную» информацию.

Может ли кто-нибудь помочь мне понять, что происходит?Почему оператор console.log показывает правильные данные, но оператор render сразу после бомбы?И как я могу это исправить?

Спасибо!

РЕДАКТИРОВАТЬ: Вот объект, который я пытаюсь визуализировать:

{ 
    assets: {
        imgs: "https://www.zzzzzzz.com/content/12626?v=1551215311"
    }
    availability: {
        forsale: true, 
        expires: "2025-12-29T05:00:00.000Z"
    }
    createdAt: "2015-01-25T05:00:00.000Z"
    description: "his is a fake description"
    modifiedAt: "2019-05-28T04:00:00.000Z"
    name: "Product Name"
    price: {
        $numberDecimal: "59.95"
    }
    sku: "ZZZZ"
    "title ": "Product Title"
    _id: "5ceec82aa686a03bccfa67cc"
}

1 Ответ

1 голос
/ 13 июня 2019

Вы пытаетесь получить доступ к объекту, прежде чем он будет готов. Два места, где у вас выдается ошибка - это подсвойства. Таким образом, для всего остального начальное значение равно «undefined», с которым ваше приложение хорошо, но как только оно попытается прочитать свойство undefined, оно выдаст ошибку.

Существует три решения: 1) убедитесь, что компонент вообще не загружается, пока состояние не завершит обновление. Эта логика будет обрабатываться в родительском компоненте ProductDetails.

, если 1) не вариант, выполните одно из следующих действий:

2) установить productDetails: null, затем в ваш компонент

render() {
    console.log(this.props.product.availability.forsale);  //This will correctly show 'true' or 'false'
    if (!this.props.product) return <div />;
    return (
            // what you have above
    )
  }
}

const Details = connect(mapStateToProps, null)(ProductDetails);
export default Details;

3) Установить форму состояния по умолчанию, что-то вроде:

{ 
    assets: {
        imgs: null
    }
    availability: {
        forsale: null, 
        expires: null
    }
    createdAt: null
    description: null
    modifiedAt: null
    name: null
    price: {
        $numberDecimal: null
    }
    sku: null
    "title ": null
    _id: null
}

Это часть стандартного поведения реакции, а также проблемы с избыточностью. См. https://reactjs.org/docs/react-component.html#setstate для получения дополнительной информации о том, как setState работает и почему вы не должны рассматривать его как синхронный код.

...