const [error, setError] = useState(false);
const [loading, setLoading] = useState(true);
Then add the useEffect hook with the dependencies: id and type .
useEffect(() => { }, [id, type])
Next in the callback, add the fetchData() function to fetch data from the appropriate API. If the parameter passed is type , use the first API. If not, use the second API.
async function fetchData() { let response, url, parameter; if (type) { url = "https://node-hnapi.herokuapp.com/"; parameter = type.toLowerCase(); } else if (id) { url = "https://hn.algolia.com/api/v1/items/"; parameter = id.toLowerCase(); } try { response = await fetch(`${url}${parameter}`); } catch (error) { setError(true); } if (response) if (response.status !== 200) { setError(true); } else { let data = await response.json(); setLoading(false); setData(data); } } fetchData();
Finally, return the loading , error , data state variables as an object.
return { loading, error, data };
Whenever the user navigates to / or /:type , React renders the ListPage component . To implement this feature, first import the required modules:
import { useNavigate, useParams } from "react-router-dom"; import useFetch from "./hooks/useFetch";
Then define the function element, and then assign the dynamic parameter, type to the variable type . If there are no dynamic parameters available, set the type variable to news. Then call the useFetch hook .
export default function ListPage() { let { type } = useParams(); const navigate = useNavigate(); if (!type) type = "news"; const { loading, error, data } = useFetch(type, null); }
Next, return the appropriate JSX code depending on whether one of the loading , error or data state variables is true .
if (error) { return Something went wrong! } if (loading) { return Loading } if (data) { document.title = type.toUpperCase(); return {type} {data.map(item => navigate(`/item/${item.id}`)}> {item.title} {item.domain && open(`${item.url}`)}> ({item.domain})} )} }
First, import the appropriate modules and components, then define the default function element, attach the dynamic parameter id to the variable id , call the useFetch hook . Make sure you unstructure the response.
import { Link, useParams } from "react-router-dom"; import parse from 'html-react-parser'; import moment from "moment"; import Comments from "./components/Comments"; import useFetch from "./hooks/useFetch"; export default function PostPage() { const { id } = useParams(); const { loading, error, data } = useFetch(null, id); }
And like the ListPage component, JSX now matches based on the state of the following variables: loading , error and data .
if (error) { return Something went wrong! } if (loading) { return Loading } if (data) { document.title=data.title; return {data.title} {data.url && Visit Website} {data.author} {moment(data.created_at).fromNow()} {data.text && {parse(data.text)}} Comments }
Import the parse and moment modules . Defines the default function element Comments , takes the commentsData array as an attribute, traverses the arrays, and shows the Node component for each element.
import parse from 'html-react-parser'; import moment from "moment"; export default function Comments({ commentsData }) { return <> {commentsData.map(commentData => )} }
Next, define the Node function element just below the Comments . The Node component now renders comments, metadata, and replies to each comment (if any) by recursively rendering itself.
function Node({ commentData }) { return { commentData.text && <> {commentData.author} {moment(commentData.created_at).fromNow()} {parse(commentData.text)} } {(commentData.children) && commentData.children.map(child => )} }
In the above code block, parse is responsible for parsing the HTML stored in commentData.text , while moment is responsible for parsing the comment time and returning the associated time using the fromNow() method .
Open the Navbar.jsx file and import the NavLink module from react-router-dom . Finally, define the function element and return a parent nav with 5 NavLink elements pointing to the appropriate categories (or styles).
import { NavLink } from "react-router-dom" export default function Navbar() { return
}
Congratulations! You just built a front-end client for Hacker News.
Hope the article is useful to you!