简体   繁体   中英

Data fetched with axios flickering on page load

I'm building out a new marketing website for my company in Gatsby, utilizing axios to fetch data from a REST api to dynamically display a list of dealers, and then dynamically displaying the contact information of the chosen dealer throughout the site. This is done by setting a cookie, which carries the ID of the dealer on the API, and then will fetch that dealer's info based on the cookie. However, I'm encountering an issue where the name of the dealer, which I'm currently displaying in the header, flickers on every page load. It looks bad, so I'm wondering if there is a way to either cache that data, or not force it to fetch on every page load and eliminate the flicker. I'm still in development, so I've got it staged on Netlify here , and you can take a look at the live version.

Here is my hook.

use-fetch.ts

import { useEffect, useState } from 'react';
import axios from 'axios';

export const useFetch = (url: string) => {
  const [status, setStatus] = useState('idle');
  const [data, setData] = useState([]);

  useEffect(() => {
    if (!url) return;
    const fetchData = async () => {
      setStatus('fetching');
      const result = await axios(url);
      setData(result.data);
      setStatus('fetched');
    };

    fetchData();
  }, [url]);

  return { status, data };
};

I'm then able to consume this in the pages like so:

const [query] = useState('https://jsonplaceholder.typicode.com/users/1/');
const url = query && 'https://jsonplaceholder.typicode.com/users/${cookie}';
const { data } = useFetch(url);

This sets an initial state users/1/ that will display the information for the first dealer unless a cookie is set.

I use this in a layout component, and I can pass the data prop down to my Header component.

app-layout.tsx

import React, { ReactNode, useEffect, useState } from 'react';

import Logo from '../../assets/svg/logo.svg';

import { Header } from '../header/Header';
import { Footer } from '../footer/Footer';
import { Devtools } from '../devtools/Devtools';

import s from './AppLayout.scss';

import { useCookie } from 'hooks/use-cookie';
import { useFetch } from 'hooks/use-fetch';

interface AppLayoutProps {
  menuItems: any;
  children: ReactNode;
}

const isDev = process.env.NODE_ENV === 'development';

// tslint:disable no-default-export
export default ({ children, menuItems }: AppLayoutProps) => {
  // copyright year
  const [year, setDate] = useState<any>();

  // setting cookie to be referenced in the useFetch hook, setting the query for dealer specific information
  const [cookie] = useCookie('one-day-location', '1');

  // the API call
  const [query, setQuery] = useState('https://jsonplaceholder.typicode.com/users/1/');
  const url = query && `https://jsonplaceholder.typicode.com/users/${cookie}`;
  const { data } = useFetch(url);

  const getYear = () => setDate(new Date().getFullYear());

  useEffect(() => {
    getYear();
  }, []);

  return (
    <div className={s.layout}>
      <Header menuItems={menuItems} data={data}></Header>

      {children}

      <Footer menuItems={menuItems} logo={<Logo />} year={year} />

      {isDev && <Devtools />}
    </div>
  );
};

And this is my use-cookie hook that is referenced throughout these components:

use-cookie.ts

import { useState } from 'react';
import Cookies from 'universal-cookie';

/**
 * Custom hook creates and returns cookie values.
 */
export const useCookie = (key: string, value: string) => {
  const cookies = new Cookies();
  const [cookie] = useState(() => {
    if (cookies.get(key)) {
      return cookies.get(key);
    }
    cookies.set(key, value);
  });

  const updateCookie = (value: string) => {
    removeItem(value);
    cookies.set(key, value);
  };

  const removeItem = (key: string) => {
    cookies.remove(key);
  };

  return [cookie, updateCookie, removeItem];
};

If you notice though, it flickers on every page load. Is there a way to store and display that data differently so that it won't do this?

Thanks in advance.

So, I was able to figure out a better solution with a bit of digging. Rather than trying to debug the hook that I built, I'm using axios-hooks , which has all of the same functionality that I needed, but solves the problem. In my layout, I've got the data being fetched like so:

const [cookie, updateCookie] = useCookie('one-day-location', '1');

const [{ data, loading, error }] = useAxios(
  `https://jsonplaceholder.typicode.com/users/${cookie}`,
);

And I'm then able to pass the data down to my Header component, but it doesn't load the API multiple times, and eliminates the flickering. I can absolutely add more documentation here in my answer if anyone has any more questions.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM