Reputation: 663
So I am preety new to react js. I am creating a blog app. I am storing blog data in the state and passing it to the children component. In the following piece of the code, I have Feeds component where I am fetching data from the json and storing it in the state. I a passing the data to children component Feed through props. Now I have an article component which is the child of the Feed which opens as a modal. The problem however is no matter which Feed I click on, it opens the same article (whichever was last enetered).
Feeds.jsx
import React, { Component } from "react";
import axios from "axios";
import Feed from "./Feed";
class Feeds extends Component {
constructor(props) {
super(props);
this.state = {
isLoaded: false,
feeds: []
};
}
componentDidMount() {
axios
.get("http://localhost:5000/api/items")
.then(res => res.data)
.then(data => {
this.setState({ isLoaded: true, feeds: data });
console.log("data " + data);
})
.catch(err => console.log("Error !! : " + err));
}
render() {
let { isLoaded, feeds } = this.state;
if (!isLoaded) {
return (
<div>
<h4> Loading ..</h4>
</div>
);
} else {
return (
<div className="container-fluid">
<Feed feedData={feeds} key={feeds.id} />
</div>
);
}
}
}
// const style for class Feed
export default Feeds;
Feed.jsx
import React, { Component } from "react";
import "bootstrap/dist/css/bootstrap.css";
import Article from "../component/Article";
class Feed extends Component {
constructor(props) {
super(props);
this.state = {
showModal: false
};
}
showModal() {
this.setState({ showModal: true });
}
hideModal() {
this.setState({ showModal: false });
}
render() {
console.log("Id: " );
console.log(this.props.feedData, "feedData");
let modalClose = () => this.setState({ showModal: false });
return (
<div className="container-fluid">
<ul className="list-group" key={this.props.feedData.id}>
{this.props.feedData.map(feed => (
<li
className="list-group-item"
style={styles.container}
key={feed.id}
>
<div className="container">
<div className="col-md-12">
<button
type="button"
className="btn btn-default"
onClick={() => this.showModal()}
>
<h3 style={styles.heading}>{feed.title} </h3>
</button>
<p>by - {feed.author}</p>
<p>{feed.subTitle}</p>
<div>
<span className="badge">Posted {feed.date}</span>
<div className="pull-right">
<button className="btn btn-primary">Upvote</button>{" "}
<button className="btn btn-info">Comment</button>{" "}
<button className="btn btn-danger">Report</button>{" "}
</div>
</div>
<br />
<Article
key={feed.id}
show={this.state.showModal}
onHide={modalClose}
data={feed}
/>
</div>
<hr />
</div>
</li>
))}
</ul>
</div>
);
}
}
Article.jsx
import React, { Component } from "react";
import { Button, Modal } from "react-bootstrap";
class Article extends Component {
constructor(props) {
super(props);
this.state = {};
}
render() {
console.log("This is working. Visibility: " + this.props.visible);
console.log("This is the id of the feed: " + this.props.key);
return (
<div className="article">
<Modal
{...this.props}
size="lg"
aria-labelledby="contained-modal-title-vcenter"
centered
>
<Modal.Header closeButton>
<Modal.Title id="contained-modal-title-vcenter">
{this.props.data.title}
</Modal.Title>
</Modal.Header>
<Modal.Body>
<h4> {this.props.data.subTitle} </h4>
<p>{this.props.data.content}</p>
</Modal.Body>
<Modal.Footer>
<Button onClick={this.props.onHide}>Close</Button>
</Modal.Footer>
</Modal>
</div>
);
}
}
export default Article;
I have setup the title in Feed.jsx as a button to open modal. Each Feed is opening the same article and on console. it shows that the props id is undefined..
console:
Id: Feed.jsx:22
(2) […]
0: Object { _id: "5cf24b53431f5f089496354b", author: "Arjun", title: "Liberalism and Loyality", … }
1: Object { _id: "5cf7a4b26332500efc0d1919", author: "Kapil Goel", title: "Made my first website", … }
length: 2
<prototype>: Array []
feedData Feed.jsx:23
Warning: Each child in a list should have a unique "key" prop.
Check the render method of `Feed`.for more information.
in li (at Feed.jsx:29)
in Feed (at Feeds.jsx:38)
in div (at Feeds.jsx:37)
in Feeds (created by Context.Consumer)
in Route (at App.js:14)
in div (at App.js:11)
in App (at src/index.js:10)
in Router (created by BrowserRouter)
in BrowserRouter (at src/index.js:9) index.js:1375
e index.js:1375
React 5
render Feed.jsx:26
React 13
componentDidMount Feeds.jsx:19
This is working. Visibility: undefined Article.jsx:10
This is the id of the feed: undefined Article.jsx:11
This is working. Visibility: undefined Article.jsx:10
This is the id of the feed: undefined Article.jsx:11
feedData is Array: false Feeds.jsx:20
GEThttp://localhost:3000/sockjs-node/432/v3s4dxpn/websocket
Upvotes: 0
Views: 157
Reputation: 103
We can't use the key
keyword as a custom prop in react component because it is pre-reserved in react.
Mostly, key
keyword is used in iteration to identify the element in the loop or provide a unique identity to element in the loop.
You can use feedId
as a prop,
<Article
// key={feed.id}
feedId={feed.id} // you can use feedId instead of key
show={this.state.showModal}
onHide={modalClose}
data={feed}
/>
Also in Article.jsx
, You are using this.props.visible
to console but you have not passed it as a prop.
Upvotes: 3
Reputation: 310
axios
.get("http://localhost:5000/api/items")
.then(res => res.data)
.then(data => {
this.setState({ isLoaded: true, feeds: data });
})
.catch(err => console.log("Error !! : " + err));
If you could console.log the data before you put it in setState. It is important to know whether data is in array format or not. You either cannot access feeds.id for the "key" prop for the Feed component in Feeds or you might have a bigger problem because you serve the Feed component an Object even tho it expects an array
Upvotes: 0