Инициализирующий запрос данных с севера в react-redux
При первом входе пользователя на страницу нужно отображать данные, из того что я прочитал, лучшее место для выборки начальных данных - это запрос еще до описания корневого компонента App.
import fetchIndexData from "./api/axios/fetchIndexData";
store.dispatch(fetchIndexData());
export default class App extends Component {
render() {
return (
<Provider store={store}>
<... тут роутинг и все такое>
</Provider>
)
}
}
Потом по идее данные попадают в компонент Promo, он отображается первым и опирается на эти самые данные, выводя их в цикле (там приходит массив с товарами). Но при данном способе ответ от сервера все равно не успевает прийти, и первый раз компонент выдает ошибку про undefined в props. Я решил это defaultProps-заглушкой, компонент вхолостую прогоняет пустой массив, на секунду отрисовывая полупустой компонент, потом приходит ответ от сервера и нормальные props - они и выводятся уже в цикле.
class Promo extends Component {
static defaultProps = {
initialListOfProducts: { data: [] }
};
render() {
const { data } = this.props.initialListOfProducts;
return (
<section>
<ul>
{data.map(item => {
return (
<ProductCard key={item.id} item={item}/>
)
})}
</ul>
</section>
)
}
}
function mapStateToProps(state) {
return {
initialListOfProducts: state.db.initialListOfProducts,
}
}
function mapDispatchToProps(dispatch) {
return {
fetchIndexData: () => {
dispatch(api.fetchIndexData());
},
}
}
export default connect(mapStateToProps, mapDispatchToProps)(Promo);
Вопрос: есть ли способ как-то удобнее получать данные от сервера при первой отрисовке сайта, чтобы не выполнять этот первый асинхронный запрос, а сразу иметь инициализирующей данные? Или тут только такой вариант или просто спиннер какой-нибудь показывать?
Ответы (1 шт):
Вы можете сделать проверку в отрисовке (render) и вернуть null, когда данных нет. Компонент не будет отрисован.
При получении данных с сервера они будут отображены как вам надо.
class Promo extends Component {
static defaultProps = {
products: []
};
render() {
if (!(this.props.products && this.props.products.length)) {
return null;
}
return (
<section>
<ul>
{this.props.products.map(item => {
return (
<ProductCard key={item.id} item={item}/>
)
})}
</ul>
</section>
)
}
}
function mapStateToProps(state) {
return {
products: state.db.products,
}
}
Не передавайте данные компоненту, которые он не использует, иначе он будет бесполезно перерисовываться.