'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