'Display data only in certain path reactjs
I'd like to display comments only in the page they are coming from. I store them in a file where I store the path as well. I am using Docusaurus as a SSG. I added <CommentBox /> on all of my .md pages. CommentBox component is composed of a form and the comment list.
//CommentBox.js
import CommentsList from "./CommentList";
import CommentForm from "./CommentForm";
import React from 'react';
class CommentBox extends React.Component {
render() {
return (
<div>
<CommentForm />
<CommentsList />
</div>
);
}
};
export default CommentBox;
Here is my code for CommentList, the one that I want to appear only in the right path:
//CommentList.js
import React, { useState } from 'react';
import { useLocation } from 'react-router-dom'
import styles from "./styles.module.css";
import commentList from '../../../static/comments/approved-comments_submissions.json'
const formatDate = (dateString) => {
const options = { year: "numeric", month: "long", day: "numeric" }
return new Date(dateString).toLocaleDateString(undefined, options)
}
const displayNbComments = (nbComm) => {
if ( nbComm <= 1){
return(
<h3>{nbComm} commentaire</h3>
);
}
return (
<h3>{nbComm} commentaires</h3>
);
}
const Comments = commentList.map((item) => {
const dateString = item.created_at;
const location = useLocation();
const path = location.pathname;
const pathComment = item.data.urlpage
const blabla = item.data.commentaire;
const [display, setDisplay] = useState( path === pathComment ? true : false);
return(
<>
{display && (
<div className={styles.comments} >
<div className={styles.author}>
<img
src={"https://ui-avatars.com/api/?name=" + item.data.name + "&background=random"}
style={{ width: 50, height: 50, borderRadius: 50 / 2, float: 'inherit'}}
alt='userIcon'
/>
<div className={styles.metadata}>
<div className={styles.fullName}>{item.data.name}</div>
<date>{formatDate(dateString)}</date>
</div>
</div>
<p>{item.data.commentaire}</p>
</div>
)}
</>
);
} )
class CommentsList extends React.Component {
render() {
const nbComm = Comments.length
return (
<div>
<p></p>
{displayNbComments(nbComm)}
{Comments}
</div>
);
}
};
export default CommentsList;
I then have a CommentForm component which is the form where data comes from.
Then, I created a CommentBox component to gather both my form and my CommentList.
however is does not compile, and for each page I have this error
[ERROR] Docusaurus Node/SSR could not render static page with path /carnets/italie/2020/j1/ because of following error:
ReferenceError: Cannot access 'components_CommentBox' before initialization
at Object.Z (main:21021:29)
at MDXContent (main:15271:7114)
at d (main:84851:498)
at bb (main:84854:16)
at a.b.render (main:84860:43)
at a.b.read (main:84859:83)
at Object.exports.renderToString (main:84870:138)
at doRender (main:18221:356)
at async serverEntry_render (main:18217:284)
Thanks
Solution 1:[1]
Ok so to answer my own question.
You cannot use hooks (useLocation) inside class components, you can only use them in functions. This was the main error.
So basically I created a CommentList function regrouping both my Comment and CommentList component.
Then, instead of using a && condition, I used a filter before the map.
Which gives us:
import React from 'react';
import { useLocation } from 'react-router-dom'
import styles from "./styles.module.css";
import commentList from '../../../static/comments/approved-comments_submissions.json'
const formatDate = (dateString) => {
const options = { year: "numeric", month: "long", day: "numeric" }
return new Date(dateString).toLocaleDateString(undefined, options)
}
const displayNbComments = (nbComm) => {
if ( nbComm <= 1){
return(
<h3>{nbComm} commentaire</h3>
);
}
return (
<h3>{nbComm} commentaires</h3>
);
}
function CommentList() {
const location = useLocation();
const path = location.pathname;
const nbComm = commentList.filter(item => item.data.urlpage === path).length;
return (
<div>
<p></p>
{displayNbComments(nbComm)}
{commentList.filter(item => item.data.urlpage === path).map((item) => {
const dateString = item.created_at;
return(
<>
<div className={styles.comments} >
<div className={styles.author}>
<img
src={"https://ui-avatars.com/api/?name=" + item.data.name + "&background=random"}
style={{ width: 50, height: 50, borderRadius: 50 / 2, float: 'inherit'}}
alt='userIcon'
/>
<div className={styles.metadata}>
<div className={styles.fullName}>{item.data.name}</div>
<date>{formatDate(dateString)}</date>
</div>
</div>
<p>{item.data.commentaire}</p>
</div>
</>
);
}
)}
</div>
);
};
export default CommentList;
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Laure D |
