Javascript 在刷新页面之前,Rest API响应不会更新
我有一个组件,显示用户选择的经销商的联系信息。更具体地说,用户选择他们的位置,设置cookie,然后使用cookie定义API调用。我使用Axios在该位置提取经销商的联系信息,将其存储在上下文中,然后根据需要通过几个组件显示信息:标题、“当前位置”组件等 我目前遇到的问题是,例如,Javascript 在刷新页面之前,Rest API响应不会更新,javascript,reactjs,rest,axios,gatsby,Javascript,Reactjs,Rest,Axios,Gatsby,我有一个组件,显示用户选择的经销商的联系信息。更具体地说,用户选择他们的位置,设置cookie,然后使用cookie定义API调用。我使用Axios在该位置提取经销商的联系信息,将其存储在上下文中,然后根据需要通过几个组件显示信息:标题、“当前位置”组件等 我目前遇到的问题是,例如,标题中显示的联系人信息在用户硬刷新页面之前不会更新,因此,假设按钮的默认文本类似于“查找经销商”,一旦选择经销商,按钮标签应显示用户选择的经销商名称。目前,它不是这样工作的。下面是标题组件和我的ApiContext的
标题中显示的联系人信息在用户硬刷新页面之前不会更新,因此,假设按钮的默认文本类似于“查找经销商”,一旦选择经销商,按钮标签应显示用户选择的经销商名称。目前,它不是这样工作的。下面是标题
组件和我的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
,我仍然只看到页面刷新时按钮更新。还有什么地方你可以指导我吗?你可以通过放置控制台进行调试。日志/调试器来检查你的代码是如何重新水合的?特别是哪一部分?我想检查数据是否正确填充。问题已用屏幕截图更新!非常感谢。