У меня есть следующая переменная state и метод componentDidMount на моем компоненте:
state = {
categorized_items: []
}
componentDidMount() {
this.props.fetchItems()
// I'm trying to do the following
console.info('uncat_items: ', this.props.uncat_items)
this.setState({categorized_items: this.props.uncat_items})
}
render () {....}
function mapStateToProps({ items_reducer }) {
return {
uncat_items: items_reducer.uncat_items
}
}
Метод действия this.props.fetchItems() извлекает ряд элементов и просто обновляет uncat_items в хранилище redux (я без проблем вижу ожидаемые значения для переменной this.props.uncat_items в методах render / other). Однако то, что мне нужно сделать в этом конкретном случае, - это сразу после того, как метод fetchItems будет выполнен и он обновит uncat_items в магазине, мне нужно вызвать setState и обновить categorized_items в состоянии с uncat_items. Я знаю, что вызывать this.setState таким образом в методе componentDidMount неправильно, но я не знаю, как это сделать. Как видите, я попытался распечатать this.props.uncat_items, но он вернул пустой массив, хотя он выполнил метод действия и правильно обновил в редукторе. Может кто-нибудь дать мне идею, как это сделать правильно? По сути, после выполнения componentDidMount установите состояние с определенной переменной из обновленного хранилища redux.
почему бы просто не использовать this.props.uncat_items непосредственно в функции рендеринга (или там, где вы хотите использовать this.state.categorized_items)?
Если вам не нужно редактировать отдельную копию данных, лучше всего не копировать ваши реквизиты в ваше состояние. Вместо этого вы можете использовать условный рендеринг в функции render, например return this.props.uncat_items.length > 0 ? <ul>...</ul> : <p>No items</p>



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Вы можете использовать метод жизненного цикла componentDidUpdate. Похоже, что когда ваш компонент монтирует ваш магазин, он все еще может содержать значение по умолчанию для этой части состояния. Затем он правильно обновляется в хранилище redux, как вы упомянули, но состояние компонента не обновляется.
Чтобы обновить состояние компонента после того, как компонент получил новые реквизиты:
componentDidUpdate(prevProps){
// compare prevProps to current props and update
if (this.props.uncat_items !== prevProps.uncat_items) {
this.setState({categorized_items: this.props.uncat_items})
}
}
Как упоминалось в комментариях, использование props непосредственно в методе рендеринга является более идеальным решением, поскольку вы не хотите, чтобы ваш компонент без необходимости повторно рендерил.
Я бы не сказал, что это оптимальное решение, так как это вызовет еще один повторный рендеринг компонента.
Да, в идеале опору следует использовать напрямую, как указано в документации. Хотя полезно продемонстрировать оператору, почему свойство и состояние не соответствуют его ожиданиям на данном этапе жизненного цикла компонента.
Проблема в вашем коде заключается в том, что вы вызываете асинхронное действие (this.props.fetchItems()), а затем немедленно вызываете this.setState(), что происходит до завершения запроса fetchItems (таким образом, до заполнения props.uncat_items).
Предполагая, что вы используете новейшую версию React, в зависимости от конкретного варианта использования вы можете:
1) Отбросьте состояние и просто используйте this.props.uncat_items напрямую в функции рендеринга.
2) Используйте static getDerivedStateFromProps для обновления состояния из-за новых свойств.
тем не мение, как упоминалось в документы, на самом деле не рекомендуется, поскольку в большинстве случаев можно обрабатывать по-другому (например, переключаясь на управляемый компонент, как указано в решении № 1). Более подробное описание можно найти в эта статья, который также упоминается в документации.
Ваш
console.info()выдал пустой массив, потому что это не асинхронный вызов; он был выполнен до того, какfetchItems()вернул какие-либо данные. (ЕслиfetchItems()возвращает обещание, вы можете легко это исправить.)