I am working on a News Web Application in React.js, and I am trying to figure out how to route a user to another component's page containing more information about the article they clicked. I've tried a lot of things but I'm pretty lost. I created a hook that fetches the data from a url link with its given data of a news article.
import { useState, useEffect } from 'react';
export const useHttp = (url, dependencies) => {
const [isLoading, setIsLoading] = useState(false);
const [fetchedData, setFetchedData] = useState(null);
useEffect(() => {
setIsLoading(true);
console.log('Sending Http request');
fetch(url)
.then(res => {
if (!res.ok) {
throw new Error('Failed to fetch');
}
return res.json();
})
.then(data => {
console.log(data);
setIsLoading(false);
setFetchedData(data); //something here
})
.catch(err => {
console.log(err);
setIsLoading(false);
});
// eslint-disable-next-line
}, dependencies);
return [isLoading, fetchedData];
};
I have several components, with very similar functionality, that use this hook to grab all of the articles from a url particular to that component and maps its data to get values that are later mapped to populate a card component that is called in all of these other components, so that the news articles show on the currently viewed page. Here is a component for science news.
import React from 'react';
import { Spinner, CardDeck } from 'react-bootstrap';
import { CardElement } from './Card';
import { useHttp } from '../hooks/http';
const sciUrl = 'http://newsapi.org/v2/top-headlines?country=us&category=science&apiKey=60d859683c7d4ae68160e82bcc4d39ea';
export const SciNews = () => {
const [isLoading, fetchedData] = useHttp(sciUrl, []);
// const classes = useStyles();
const sciNews = fetchedData
? fetchedData.articles.map((article, index) => ({
image: article.urlToImage,
name: article.source.name,
title: article.title,
description: article.description,
id: index,
}))
: [];
let content = <Spinner animation="grow" />;
if (!isLoading && sciNews && sciNews.length > 0) {
content = (
<div>
{sciNews.map((article) => (
<CardElement key={article.id} article={article} />
))}
</div>
);
} else if (!isLoading && (!sciNews || sciNews.length === 0)) {
content = <p>Could not fetch any data.</p>;
}
return content;
};
const sciHomeUrl = 'http://newsapi.org/v2/top-headlines?country=us&category=science&pageSize=3&sortBy=popularity&apiKey=60d859683c7d4ae68160e82bcc4d39ea';
export const SciHomeNews = () => {
const [isLoading, fetchedData] = useHttp(sciHomeUrl, []);
// const classes = useStyles();
const sciHomeNews = fetchedData
? fetchedData.articles.map((article, index) => ({
image: article.urlToImage,
name: article.source.name,
title: article.title,
description: article.description,
id: index,
}))
: [];
let content = <Spinner animation="grow" />;
if (!isLoading && sciHomeNews && sciHomeNews.length > 0) {
content = (
<CardDeck style={{paddingLeft: "5%", paddingRight: "5%"}}>
{sciHomeNews.map((article) => (
<CardElement key={article.id} article={article} />
))}
</CardDeck>
);
} else if (!isLoading && (!sciHomeNews || sciHomeNews.length === 0)) {
content = <p>Could not fetch any data.</p>;
}
return content;
};
Here is the Card Component..
import React from 'react';
import { Card, Button } from 'react-bootstrap';
export const CardElement = ({ article }) => (
<Card
style={{ height: '75vh' }}
key={article.id}
bg="dark"
text="white"
className="my-3"
>
<Card.Img style={{ height: '50%' }} variant="top" src={article.image} />
<Card.Body>
<Card.Text>{article.name}</Card.Text>
<Card.Title>{article.title}</Card.Title>
<Card.Text>{article.description}</Card.Text>
</Card.Body>
</Card>
);
How can I add a button or link to the card component to route the user to a details page, showing only the article clicked? I would like to include the actual content, author, date, etc. on this page of just that 1 article. Thanks