Hey guys! I'm building an app with Ionic React. I have a master page that displays a list of news, and a detail page displaying a single news. On the news detail page, I have a lit of random news displayed underneath the main news at the top.
Switching from the master page to the detail page works fine. I use the routerLink prop on an IonicCard and that works fine. But on the single news page, the list of news when clicked on, flicks the page, updates the URL but doesn't update the view. I have to manually reload the page for it to send the request to fetch the new news detail. You'll find the single news component code below:
import React, { useEffect } from 'react'
import {
IonButtons,
IonContent,
IonHeader,
IonMenuButton,
IonPage,
IonTitle,
IonToolbar,
IonCard,
IonIcon,
IonCardContent,
IonCardSubtitle,
IonCardHeader,
IonCardTitle,
IonLoading,
IonGrid,
IonRow,
IonCol,
} from '@ionic/react'
import {
FacebookShareButton,
TwitterShareButton,
TelegramShareButton,
WhatsappShareButton,
TelegramIcon,
WhatsappIcon,
FacebookIcon,
TwitterIcon,
} from 'react-share'
import useSingleNews from '../hooks/useSingleNews'
import { RouteComponentProps, Redirect } from 'react-router'
import NewsInterface from '../interfaces/NewsInterface'
import SEO from '../components/SEO'
import { TWITTER_HANDLE } from '../utils/constants'
import colors from '../utils/colors'
interface Props extends RouteComponentProps<{
newsHash: string
}> { }
const SingleNews: React.FC<Props> = ({ match }) => {
const { data, loading, error } = useSingleNews(match.params.newsHash)
useEffect(() => {
console.log(data)
}, [data])
if (loading) return <IonLoading
isOpen={loading}
message={`Patientez s'il vous pla卯t...`}
/>
if (error) return <Redirect to="/404" />
const ShareButtons = () => {
const url = window.location.href
const title = `${data?.title} - Ha茂ti Info Toutan (HIT)`
const hashtags = `HIT partage news`
return (
<IonRow>
<IonCol>
<FacebookShareButton
url={url}
quote={title}
hashtag={hashtags.split(' ').join(' #')}>
<FacebookIcon size={48} style={{ borderRadius: 4, color: colors.facebook }} />
</FacebookShareButton>
</IonCol>
<IonCol>
<TwitterShareButton
url={url}
title={title}
via={TWITTER_HANDLE}
hashtags={hashtags.split(' ')}>
<TwitterIcon size={48} style={{ borderRadius: 4, color: colors.twitter }} />
</TwitterShareButton>
</IonCol>
<IonCol>
<WhatsappShareButton url={url} title={title}>
<WhatsappIcon size={48} style={{ borderRadius: 4, color: colors.whatsapp }} />
</WhatsappShareButton>
</IonCol>
<IonCol>
<TelegramShareButton url={url} title={title}>
<TelegramIcon size={48} style={{ borderRadius: 4, color: colors.telegram }} />
</TelegramShareButton>
</IonCol>
</IonRow>
)
}
return (
<IonPage>
<IonHeader>
<IonToolbar>
<IonButtons slot="start">
<IonMenuButton />
</IonButtons>
<IonTitle>{data?.title} - HIT</IonTitle>
</IonToolbar>
</IonHeader>
<IonContent>
<IonGrid>
<IonRow>
<IonCol key={data?.hash} size="12" sizeSm="6">
<IonCard>
{!!data?.image_url && (<img src={data?.image_url} alt={data?.title} />)}
<IonCardHeader>
<IonCardSubtitle>{data?.public_date}</IonCardSubtitle>
</IonCardHeader>
<IonCardContent>
<div dangerouslySetInnerHTML={{ __html: `${data?.body}` }} />
</IonCardContent>
{!!data?.ads && (
<IonCardHeader>
<IonCardSubtitle>
<div dangerouslySetInnerHTML={{ __html: `${data?.ads}` }} />
</IonCardSubtitle>
</IonCardHeader>
)}
<IonCardHeader>
<ShareButtons />
</IonCardHeader>
</IonCard>
</IonCol>
</IonRow>
{data?.randoms ? (
<>
<h3 className="ion-padding-horizontal">Autres Nouvelles</h3>
<IonRow>
{data?.randoms.map((news: NewsInterface) => (
<IonCol key={news.hash} size="12" sizeSm="4" sizeXl="3">
<IonCard routerLink={`/n/${news.hash}`}>
{!!news.image_url && (<img src={news.image_url} alt={news.title} />)}
<IonCardHeader>
<IonCardSubtitle>{news.public_date}</IonCardSubtitle>
<IonCardTitle>{news.title}</IonCardTitle>
</IonCardHeader>
</IonCard>
</IonCol>
))}
</IonRow>
</>
) : null}
</IonGrid>
</IonContent>
<SEO
title={`${data?.title}`}
url={window.location.href}
description={`${data?.body.split('\n')[0]}`}
image={data?.image_url}
/>
</IonPage>
)
}
export default SingleNews
Hi @jgb-solutions,
I'm not seeing anything in particular in the SingleNews component to cause issues. Would you be able to provide a slimmed down github repo that reproduces the issue?
hey @elylucas thanks for taking the time to respond.
I just made the project repo public here: https://github.com/jgb-solutions/HIT-APP.
@jgb-solutions
Thanks!
I wasn't able to get the http request to fire to the news service, but looking through the code I think the issue might be in the useSingleNews hook. The useEffect hook in there takes an empty array param, so it would only call fetchSingleNews once. I think if you passed the hash into the array it would call it each time the hash updates and pull back new data.
useEffect(() => {
fetchSingleNews()
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [newsHash])
Let me know if that fixes it.
hey @elylucas thanks a ton! It worked. Even tho I don't fully understand why, because I thought that each update of the route, would trigger a re-render of the page, and then make a request using a new instance of the hook. But it seems that that's not what's happening.
Anyway thanks a lot! I've been wondering why it wouldn't work for days.
Ya, checkout our lifecycle guide which has some info around this: https://ionicframework.com/docs/react/lifecycle
Though, I think in this case, since you were navigating to the same page it was sticking around.
Thanks for the issue! This issue is being locked to prevent comments that are not relevant to the original issue. If this is still an issue with the latest version of Ionic, please create a new issue and ensure the template is fully filled out.
Most helpful comment
Ya, checkout our lifecycle guide which has some info around this: https://ionicframework.com/docs/react/lifecycle
Though, I think in this case, since you were navigating to the same page it was sticking around.