I've got component that displays contact information from a dealer as chosen by the user. To be more specific, a user selects their location, setting a cookie which then is used to define the API call. I pull in the contact information of the dealer in that location using Axios, store it in a context, and then display the information as necessary through several components: the header, a "current location" component etc. However, I'm having an issue with the content flickering each time the page is refreshed.
I've tried storing the JSON response in local storage, but, for a brief moment on page load, it shows as undefined, making the flicker continue. Obviously, I'm needing to eliminate that so that the data persists.
I've got it working via ApiContext, and I'm displaying the data in my Header component. Below is the code for both:
ApiContext.tsx
import React, { createContext, useEffect, useState } from 'react';
import axios from 'axios';
const contextObject = {} as any;
export const context = createContext(contextObject);
export const ApiContext = ({ children }: any) => {
const [selectedDealer, setselectedDealer] = useState(`1`);
useEffect(() => {
axios
.get(`${process.env.GATSBY_API_ENDPOINT}/${selectedDealer}`)
.then((response) => setselectedDealer(response.data));
}, [selectedDealer]);
const changeDealer = (id: any) => {
setselectedDealer(id);
};
const { Provider } = context;
return (
<Provider value={{ data: selectedDealer, changeDealer: changeDealer }}>
{children}
</Provider>
);
};
Header.tsx
import React, { ReactNode, useContext, useEffect, useState } from 'react';
import Logo from 'assets/svg/logo.svg';
import css from 'classnames';
import { Button } from 'components/button/Button';
import { Link } from 'components/link/Link';
import { MenuIcon } from 'components/menu-icon/MenuIcon';
import { context } from 'contexts/ApiContext';
import { NotificationBar } from '../notification-bar/NotificationBar';
import s from './Header.scss';
import { MainNav } from './navigation/MainNav';
interface HeaderProps {
navigationContent: ReactNode;
}
export const Header = ({ navigationContent }: HeaderProps) => {
const [scrolled, setScrolled] = useState(false);
const [open, setOpen] = useState(false);
const data = useContext(context);
const buttonLabel = data ? data.name : 'Find a Dealer';
const buttonLink = data ? `tel:${data.phone}` : '/find-a-dealer';
useEffect(() => {
const handleScroll = () => {
const isScrolled = window.scrollY > 10;
if (isScrolled !== scrolled) {
setScrolled(!scrolled);
}
};
document.addEventListener('scroll', handleScroll, { passive: true });
return () => {
document.removeEventListener('scroll', handleScroll);
};
}, [scrolled]);
return (
<>
<NotificationBar notificationContent={navigationContent} />
<header className={scrolled ? css(s.header, s.header__scrolled) : s.header}>
<nav className={s.header__navigation}>
<ul className={s.header__container}>
<li className={s.header__logo}>
<Link to="/" className={s.header__link}>
<Logo />
</Link>
</li>
<li className={s.header__primary}>
<MainNav navigationItems={navigationContent} />
</li>
<li className={s.header__utility}>
<Button href={buttonLink}>{buttonLabel}</Button>
</li>
<li className={s.header__icon}>
<MenuIcon onClick={() => setOpen(!open)} />
</li>
</ul>
</nav>
</header>
</>
);
};
I would assume that this is because the API call is being triggered each time the page is refreshed, so I wonder if there's any way to persist the data in a more efficient way?
Thanks in advance!