I have a List of products-ID and a button. When I press the button, I want to refresh the data in the ListComponent. I have no idea how can I do this in React. Can someone help me?
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")
}))
};
};
I have a List of products-ID and a button. When I press the button, I want to refresh the data in the ListComponent. I have no idea how can I do this in React. Can someone help me?
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")
}))
};
};
Share
Improve this question
edited Dec 5, 2018 at 9:38
Kathrine Hanson
asked Dec 5, 2018 at 9:13
Kathrine HansonKathrine Hanson
6154 gold badges11 silver badges33 bronze badges
14
-
You only should use
forceUpdate
if yourrender
method depends on data other than state or props. In your case it's useless. – hindmost Commented Dec 5, 2018 at 9:32 -
By "refresh the data" do you intend to set the products property to
null
? Or is there new data ing in from somewhere else? – djfdev Commented Dec 5, 2018 at 9:33 - @hindmost okay! can u give me a hint how will I refresh the data of ListComponent as I dont know? – Kathrine Hanson Commented Dec 5, 2018 at 9:33
- how will I refresh the data of ListComponent.. It depends on where your data e from exactly. – hindmost Commented Dec 5, 2018 at 9:35
- @djfdev no. I dont want to set the products property to null. What I really want to do is to do a refresh because from somewhere else some new products may be added. I thought to set the state to null and then display the new state but this is not a good way. Do u have any idea how will I refresh the data? – Kathrine Hanson Commented Dec 5, 2018 at 9:35
2 Answers
Reset to default 1Your refresh function needs to call an action that fetches the data, and updates the Redux store accordingly. And because you've mapped part of your Redux state to this ponent's props, it will re-render when that data is fetched and saved via the reducer.
Therefore, you don't need to set local state at all in this ponent. Provided you have an action called 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
ponentDidMount () {
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)
Again, this assumes that fetchProductData
dispatches an action that will update the redux state where products are stored. Passing the action to connect
like this will make it available as a prop within the ponent.
It looks like you've placed your refresh()
inside the constructor, try:
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
}))}
/>
);
}
I made a minimal ponent that does what you want it to do. Instead of binding in the constructor i use a fat arrow function for refresh.
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;
You don't need to forceUpdate()
, the ponent will re-render by default when its props are changed.
For an explanation of the fat arrow and what it does to this
, check out https://hackernoon./javascript-es6-arrow-functions-and-lexical-this-f2a3e2a5e8c4.