#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
или просто использовать логический оператор, такой как||
inmapStateToProps()
или даже inrender()
. Есть много способов, это зависит от вашего приложения. Возможно, поделитесь своим редуктором для получения дополнительной информации о структуре вашего хранилища.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>
Надеюсь, это поможет!