Javascript 在刷新页面之前,Rest API响应不会更新

Javascript 在刷新页面之前,Rest API响应不会更新,javascript,reactjs,rest,axios,gatsby,Javascript,Reactjs,Rest,Axios,Gatsby,我有一个组件,显示用户选择的经销商的联系信息。更具体地说,用户选择他们的位置,设置cookie,然后使用cookie定义API调用。我使用Axios在该位置提取经销商的联系信息,将其存储在上下文中,然后根据需要通过几个组件显示信息:标题、“当前位置”组件等 我目前遇到的问题是,例如,标题中显示的联系人信息在用户硬刷新页面之前不会更新,因此,假设按钮的默认文本类似于“查找经销商”,一旦选择经销商,按钮标签应显示用户选择的经销商名称。目前,它不是这样工作的。下面是标题组件和我的ApiContext的

我有一个组件,显示用户选择的经销商的联系信息。更具体地说,用户选择他们的位置,设置cookie,然后使用cookie定义API调用。我使用Axios在该位置提取经销商的联系信息,将其存储在上下文中,然后根据需要通过几个组件显示信息:标题、“当前位置”组件等

我目前遇到的问题是,例如,
标题中显示的联系人信息在用户硬刷新页面之前不会更新,因此,假设按钮的默认文本类似于“查找经销商”,一旦选择经销商,按钮标签应显示用户选择的经销商名称。目前,它不是这样工作的。下面是
标题
组件和我的
ApiContext
的代码

ApiContext.tsx

import React, { createContext } from 'react';

import axios from 'axios';
import { makeUseAxios } from 'axios-hooks';
import { useCookie } from 'hooks/use-cookie';

const contextObject = {} as any;

export const context = createContext(contextObject);

const useAxios = makeUseAxios({
  axios: axios.create({ baseURL: process.env.GATSBY_API_ENDPOINT }),
});

export const ApiContext = ({ children }: any) => {
  const [cookie] = useCookie('one-day-location', '1');
  const [{ data }] = useAxios(`${cookie}`);

  const { Provider } = context;
  return <Provider value={data}>{children}</Provider>;
};
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>
    </>
  );
};
import React,{createContext}来自“React”;
从“axios”导入axios;
从“axios挂钩”导入{makeUseAxios};
从“hooks/use cookie”导入{useCookie};
const contextObject={}如有;
export const context=createContext(contextObject);
const useAxios=makeUseAxios({
axios:axios.create({baseURL:process.env.GATSBY_API_ENDPOINT}),
});
export const ApiContext=({children}:any)=>{
const[cookie]=useCookie('1-day-location','1');
const[{data}]=useAxios(`${cookie}`);
const{Provider}=上下文;
返回{children};
};
Header.tsx

import React, { createContext } from 'react';

import axios from 'axios';
import { makeUseAxios } from 'axios-hooks';
import { useCookie } from 'hooks/use-cookie';

const contextObject = {} as any;

export const context = createContext(contextObject);

const useAxios = makeUseAxios({
  axios: axios.create({ baseURL: process.env.GATSBY_API_ENDPOINT }),
});

export const ApiContext = ({ children }: any) => {
  const [cookie] = useCookie('one-day-location', '1');
  const [{ data }] = useAxios(`${cookie}`);

  const { Provider } = context;
  return <Provider value={data}>{children}</Provider>;
};
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>
    </>
  );
};
import React,{ReactNode,useContext,useffect,useState}来自“React”;
从“assets/svg/Logo.svg”导入徽标;
从“类名”导入css;
从“组件/按钮/按钮”导入{Button};
从'components/Link/Link'导入{Link};
从“组件/菜单图标/MenuIcon”导入{MenuIcon};
从“context/ApiContext”导入{context};
从“../NotificationBar/NotificationBar”导入{NotificationBar};
从“/Header.scss”导入s;
从“./navigation/MainNav”导入{MainNav};
接口头程序{
导航内容:反应节点;
}
导出常量头=({navigationContent}:HeaderProps)=>{
const[scrolled,setScrolled]=使用状态(false);
const[open,setOpen]=useState(false);
const data=useContext(上下文);
const buttonLabel=data?data.name:“查找经销商”;
const buttonLink=data?`tel:${data.phone}`:'/find-a-dealer';
useffect(()=>{
常量handleScroll=()=>{
常量isScrolled=window.scrollY>10;
如果(已滚动!==已滚动){
设置滚动(!滚动);
}
};
addEventListener('scroll',handleScroll,{passive:true});
return()=>{
文档。删除EventListener(“滚动”,把手滚动);
};
},[滚动];
返回(
  • {按钮标签}
  • setOpen(!open)}/>
); };
这是我的控制台日志的屏幕截图,在这里我将从
ApiContext
中的
data
返回的内容记录下来


任何关于这方面的建议都将不胜感激,即使这意味着完全重构我使用它的方式。谢谢

您就快到了,您的
ApiContext
看起来不错,它检索信息并填充上下文,但是,您缺少的是一个
useState
来触发更新以强制重新激活按钮

发生的情况是,您的上下文从不更新
数据
常量。在第一次渲染时,当您的请求完成且
上下文已满,但您的按钮从未更新时,渲染为空。像这样的东西可能适合你:

  const data = useContext(context);
  const [newData, setNewData] = useState(data);
    
  const buttonLabel = newData? newData.name : 'Find a Dealer';
  const buttonLink = newData? `tel:${newData.phone}` : '/find-a-dealer';
您可能需要稍微调整代码以满足您的需求,但是,您可以保留这个想法,即使用检索到的数据创建一个状态

您可以创建
useffect
来控制数据何时更改,并根据需要填充状态:

useEffect(()=>{
  setNewData(data)
}, [data])

经过大量的挖掘,我自己也能弄明白这一点

以Ferran的建议为基础,我决定最好对显示来自某个州的联系人信息的组件进行再水化,但由于我在多个组件中使用此上下文,我需要全局更新状态。我从
makeUseAxios
转到了传统的
axios
调用。然后,经销商ID将存储在状态中并在通话中使用。我还创建了
changedelator
const,我可以将其传递给上下文,并更新状态:

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 [dealerId, setDealerId] = useState(`1`);

  useEffect(() => {
    axios.get(`${process.env.GATSBY_API_ENDPOINT}/${dealerId}`).then((res) => setDealerId(res.data));
  }, [dealerId]);

  const changeDealer = (value: any) => {
    setDealerId(value);
  };

  const { Provider } = context;
  return <Provider value={{ data: dealerId, changeDealer: changeDealer }}>{children}</Provider>;
};
然后我可以将其连接到一个按钮上,如下所示:

<Link to="/" onClick={() => changeDealer(dealer.id)}>
  Set Location
</Link>
changederator(dealer.id)}>
设置位置

这将全局更新状态,更改显示它的所有组件的联系人信息。我将把数据存储在
localStorage
项目中,允许数据在页面刷新后保持不变。

谢谢,这是一个很好的开始!结合这一点,以及
useffect
,我仍然只看到页面刷新时按钮更新。还有什么地方你可以指导我吗?你可以通过放置
控制台进行调试。日志
/
调试器
来检查你的代码是如何重新水合的?特别是哪一部分?我想检查
数据是否正确填充。问题已用屏幕截图更新!非常感谢。