Обновить данные / состояние конкретного компонента в React
У меня есть список продуктов-ID и кнопка. Когда я нажимаю кнопку, я хочу обновить данные в ListComponent. Я понятия не имею, как я могу сделать это в React. Кто-нибудь может мне помочь?
constructor(props) {
super(props);
this.state = {
products: this.props.productData //where productData an array of all products-ID
};
this.refresh = this.refresh.bind(this);
}
refresh() {
this.setState({ products: null });
this.forceUpdate();
}
render() {
const { products } = this.state;
<Button onClick={this.refresh} />
<ListComponent
data={products.map(entry => ({
text: entry.productId
}))}
/>
);
}
}
const mapStateToProps = (state, ownProps) => {
const products = selectAllProducts(state); //function that fetches-takes all products
return {
productData: products.map(products => ({
productId: product.get("productId")
}))
};
};
2 ответа
Ваша функция обновления должна вызвать действие, которое извлекает данные и соответственно обновляет хранилище Redux. И поскольку вы сопоставили часть своего состояния Redux с реквизитами этого компонента, он будет повторно отображаться при извлечении и сохранении этих данных через редуктор.
Следовательно, вам вообще не нужно устанавливать локальное состояние в этом компоненте. Если у вас есть действие под названием fetchProductData
:
class ProductList extends React.Component {
constructor (props) {
super(props)
this.refresh = this.refresh.bind(this)
}
// if you don't already have the data in your store, you can fetch it here to kick things off
componentDidMount () {
this.props.fetchProductData()
}
refresh () {
this.props.fetchProductData()
}
render () {
const { products } = this.state
return (
<div>
<Button onClick={this.refresh} />
<ListComponent
data={products.map(entry => ({
text: entry.productId
}))}
/>
</div>
)
}
}
const mapStateToProps = (state, ownProps) => {
const products = selectAllProducts(state)
return {
productData: products.map(products => ({
productId: product.get("productId")
}))
}
}
export default connect(mapStateToProps, { fetchProductData })(MyComponent)
Опять же, это предполагает, что fetchProductData
отправляет действие, которое обновит состояние редукции, где хранятся продукты. Передача действия connect
как это сделает его доступным в качестве компонента в компоненте.
Похоже, вы разместили свой refresh()
внутри конструктора попробуйте:
constructor(props) {
super(props);
this.state = {
products: this.props.productData //where productData an array of all products-ID
};
this.refresh = this.refresh.bind(this);
}
refresh() {
this.setState({ products: null });
this.forceUpdate();
}
render() {
const { products } = this.state;
<Button onClick={this.refresh} />
<ListComponent
data={products.map(entry => ({
text: entry.productId
}))}
/>
);
}
Я сделал минимальный компонент, который делает то, что вы хотите, чтобы он делал. Вместо привязки в конструкторе я использую функцию жирной стрелки для обновления.
import { Component } from "react";
const ListItem = props => props.item.text;
class List extends Component {
constructor(props) {
super(props);
this.state = {
items: [{ id: 0, text: "zero" }, { id: 1, text: "one" }]
};
}
refresh = () => {
this.setState({ items: [] });
};
render() {
const { items } = this.state;
return (
<div>
{items.map(i => (
<div key={i.id}>
<ListItem item={i} />
</div>
))}
<button onClick={this.refresh}>refresh</button>
</div>
);
}
}
export default List;
Вам не нужно forceUpdate()
, компонент будет повторно визуализирован по умолчанию при смене реквизита.
Для объяснения жирной стрелы и что она делает для this
Проверьте https://hackernoon.com/javascript-es6-arrow-functions-and-lexical-this-f2a3e2a5e8c4.