Состояние mapStateToProps возвращает ‘undefined’ два раза перед выборкой данных из firebase

#reactjs #firebase #redux #react-redux #google-cloud-firestore

# #reactjs #огневая база #сокращение #react-redux #google-облако-firestore

Вопрос:

Компонент не извлекает данные из Firebase перед монтированием.

 const mapStateToProps = (state, ownProps) => {
  return {
    products: state.firestore.ordered.products
  };
};
 

когда я проверяю наличие реквизита после его установки…

 componentDidMount() {
    console.log(this.props);
}
 

Значение this.props.product не определено.


Если я консоль.регистрируя параметр состояния внутри mapStateToProps(), я сразу получаю две консоли.журналы undefined и через некоторое время я получаю фактический массив, который я хотел.

 const mapStateToProps = (state, ownProps) => {
  const products2 = state.firestore.ordered.products;

  console.log(products2);  //returns 2 console logs of undefined,
  // after a second (after the component mounts) it gives me the data

  return {
    products: state.firestore.ordered.products
  };
};
 

Причина, по которой это проблема, заключается в том, что я хочу визуализировать компонент, используя данные из Firebase.

 <div className="item-render-space">
          {products
            .filter(
              eachProduct =>
                eachProduct.landingPageCategory.indexOf(this.props.category) >
                -1
            )
            .map(eachProduct => (
              <div className="each-product" key={eachProduct.id}>
                <Link to={"/product/"   eachProduct.id}>
                  <img src={eachProduct.image} alt="#" />
                  <p className="product-price">{eachProduct.price}</p>
                  <p className="product-name">
                    {nameShortener(eachProduct.name)}
                  </p>
                </Link>
              </div>
            ))}
        </div>
 

Я получаю экран ошибки, потому что переменная «products» не определена, поскольку данные из firebase не дошли до компонента, когда он начал рендеринг.

Как исправить эту проблему ?!

РЕДАКТИРОВАТЬ: Вот rootReducer:

 const rootReducer = combineReducers({
  firestore: firestoreReducer, //connects to firestore
  live: liveReducer, //used locally for opening bootstrap modals
  products: productsReducer, //previous products store before implementing Firestore
  firebase: firebaseReducer //connects to firebase
});
 

Комментарии:

1. Условный рендеринг (this.props.products amp;amp; this.props.products. длина> 0) или по умолчанию пустой массив [] . Это не уникально для react-redux или firebase, это обычная проблема с асинхронным извлечением данных.

2. как по умолчанию использовать пустой массив?

3. Как бы вы обычно устанавливали значение по умолчанию в своем хранилище redux? Также вы могли бы рассмотреть defaultProps или просто использовать логический оператор, такой как || in mapStateToProps() или даже in render() . Есть много способов, это зависит от вашего приложения. Возможно, поделитесь своим редуктором для получения дополнительной информации о структуре вашего хранилища.

4. Я новичок в redux и firebase, нужно ли мне создавать функцию восстановления в компоненте? Я пытался это сделать, но с треском провалился. Я попытался создать if(product !== undefined), но ничего из того, что я пробовал, не сработало. Я поделюсь редуктором 1 сек

5. Пожалуйста, поделитесь своим редуктором и как initialState он выглядит для получения дополнительной помощи. Как минимум, попробуйте следующее {products amp;amp; products.length > 0 amp;amp; . Также просмотрите следующее reactjs.org/docs/conditional-rendering.html .

Ответ №1:

Попробуйте использовать условный рендеринг, чтобы избежать попыток выполнить Array.prototype.filter() и Array.prototype.map() undefined . Следующее будет проверяться на products достоверность и иметь length значение больше 0:

 <div className="item-render-space">
  {products amp;amp; products.length > 0 amp;amp; products
    .filter(
      eachProduct =>
        eachProduct.landingPageCategory.indexOf(this.props.category) >
        -1
    )
    .map(eachProduct => (
      <div className="each-product" key={eachProduct.id}>
        <Link to={"/product/"   eachProduct.id}>
          <img src={eachProduct.image} alt="#" />
          <p className="product-price">{eachProduct.price}</p>
          <p className="product-name">
            {nameShortener(eachProduct.name)}
          </p>
        </Link>
      </div>
    ))}
</div>
 

Надеюсь, это поможет!