Guys I need your help with an issue. I am recently learning how to use React. The question is this: I have three h2 elements, each with a different id attribute. What I am trying to do is create a list consisting of as many "a" elements as there are h2 elements. Each "a" element should have the href attribute pointing to the respective h2 element.
I show you what I have tried to do. With the code I wrote the list remains blank.
import logo from './logo.svg';
import './App.css';
import { Link } from "react-router-dom";
function App() {
const h2 = Array.from(document.getElementsByTagName('h2'));
const list = h2.map(element => {
return (
<li key={element.id}>
<Link to={`${element.id}`}>{element.innerHTML}</Link>
</li>
);
})
return (
<div className="App">
<h2 id="first">First item</h2>
<h2 id="second">Second item</h2>
<h2 id="Third">Third item</h2>
<h4>List of h2:</h4>
<ul>
{list}
</ul>
</div>
);
}
export default App;
Could you tell me what I should do or the concepts I should go to study?
CodePudding user response:
There are two problems in above solution.
- Fetching H2s before they render for the first render.
- Missed appending
#
before redirection link for ID.
Here's the solution. I have used a
tag instead of react-router's Link but it will work in similar pattern.
import { useEffect, useState } from "react";
import "./styles.css";
export default function App() {
const [list, setList] = useState([]);
useEffect(() => {
// Added this in useEffect as we endup fetching h2s before they render if kept outside. Here they will be fetched post first render
const h2 = Array.from(document.getElementsByTagName("h2"));
const currentList = h2.map((element) => {
return (
<li key={element.id}>
<a href={`#${element.id}`}>{element.innerHTML}</a>
</li>
);
});
setList(currentList);
}, []);
return (
<div className="App">
<h2 id="first">First item</h2>
<h2 id="second">Second item</h2>
<h2 id="Third">Third item</h2>
<div style={{ height: "100vh" }}>Some space</div>
<h4>List of h2:</h4>
<ul>{list}</ul>
</div>
);
}
Here's a working example at codesandbox, I have added a large div in the center to make scroll visible. Please scroll down the example.
CodePudding user response:
Using useEffect
to store the text
of h2
's and creating Links from it as as below,
change the li
to Links
as required
const { useState, useEffect } = React;
function App() {
const [h2Count, setH2Count] = useState([]);
useEffect(() => {
const noOfH2s = [...document.querySelectorAll("h2")];
setH2Count(noOfH2s.map((el) => ({ text: el.innerText, id: el.id })));
}, []);
const list = h2Count.map((element, id) => {
return <li key={id}>{`${element.text}-${element.id}`}</li>;
});
return (
<div className="App">
<h2 id="first">First item</h2>
<h2 id="second">Second item</h2>
<h2 id="Third">Third item</h2>
<h4>List of h2:</h4>
<ul>{list}</ul>
</div>
);
}
ReactDOM.createRoot(document.getElementById("root")).render(<App />);
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.1.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.1.0/umd/react-dom.development.js"></script>