在盖茨比使用document.cookie



我需要能够在我的Gatsby项目中设置和访问cookie,并且我能够使用本教程获得一些可靠的设置。我正在构建一个设置cookie的挂钩,并在整个网站上使用它。这就是当一切都说出来和做出来时,帮助者的样子。

使用cookie.ts

import { useState, useEffect } from 'react';
const getItem = (key) =>
document.cookie.split('; ').reduce((total, currentCookie) => {
const item = currentCookie.split('=');
const storedKey = item[0];
const storedValue = item[1];
return key === storedKey ? decodeURIComponent(storedValue) : total;
}, '');
const setItem = (key, value, numberOfDays) => {
const now = new Date();
// set the time to be now + numberOfDays
now.setTime(now.getTime() + numberOfDays * 60 * 60 * 24 * 1000);
document.cookie = `${key}=${value}; expires=${now.toUTCString()}; path=/`;
};
/**
*
* @param {String} key The key to store our data to
* @param {String} defaultValue The default value to return in case the cookie doesn't exist
*/
export const useCookie = (key, defaultValue) => {
const getCookie = () => getItem(key) || defaultValue;
const [cookie, setCookie] = useState(getCookie());
const updateCookie = (value, numberOfDays) => {
setCookie(value);
setItem(key, value, numberOfDays);
};
return [cookie, updateCookie];
};

我将钩子调用到这样的组件中:

经销商列表.tsx

import React, { ReactNode, useEffect } from 'react';
import { Container } from 'containers/container/Container';
import { Section } from 'containers/section/Section';
import { Link } from 'components/link/Link';
import s from './DealerList.scss';
import { useCookie } from 'hooks/use-cookie';
interface DealerListProps {
fetchedData: ReactNode;
}
let cookie;

useEffect(() => {
cookie = useCookie();
}, []);

export const DealerList = ({ fetchedData }: DealerListProps) => {
const dealerInfo = fetchedData;
if (!dealerInfo) return null;

const [cookie, updateCookie] = useCookie('one-day-location', 'sacramento-ca');
return (
<>
<Section>
<Container>
<div className={s.list}>
{dealerInfo.map((dealer: any) => (
<div className={s.dealer} key={dealer.id}>
<div className={s.dealer__info}>
<h3 className={s.name}>
{dealer.company.name}
</h3>
<span className={s.address}>{dealer.address.street}</span>
<span className={s.city}>{dealer.address.city} {dealer.address.zip}</span>
</div>
<div className={s.dealer__contact}>
<span className={s.email}>{dealer.email}</span>
<span className={s.phone}>{dealer.phone}</span>
</div>
<div className={s.dealer__select}>
<Link
to="/"
className={s.button}
onClick={() => {
updateCookie(dealer.phone, 10);
}}
>
Select Location
</Link>
</div>
</div>
))}
</div>
</Container>
</Section>
</>
);
};

它在gatsby develop上运行良好,我可以访问cookie的值并相应地更改显示的联系人信息。然而,当我尝试构建或推送到Netlify时,我会遇到这个错误。

WebpackError: ReferenceError: document is not defined

我知道这与第4行和第17行的document.cookie有关,但我正在努力想办法解决它。有什么建议吗?我是进口的useEffect,从我的研究来看,这与它有关,但我能做些什么让它正常工作?

提前谢谢。

我做了更多的研究,发现了这个简单的钩子,用它替换了use-cookie.ts中的代码,对它做了一些修改(包括在下面(,安装了universal-cookie,它似乎工作得很好。这是新代码:

使用cookie.ts

import { useState } from 'react';
import Cookies from 'universal-cookie';
export const useCookie = (key: string, value: string, options: any) => {
const cookies = new Cookies();
const [cookie, setCookie] = useState(() => {
if (cookies.get(key)) {
return cookies.get(key);
}
cookies.set(key, value, options);
});
const updateCookie = (value: string, options: any) => {
setCookie(value);
removeItem(value);
cookies.set(key, value, options);
};
const removeItem = (key: any) => {
cookies.remove(key);
};
return [cookie, updateCookie, removeItem];
};

如果有人有更好的方法,请告诉我!

根据Gatsby的调试HTML构建文档:

您的一些代码引用了"浏览器全局",如windowdocument。如果这是你的问题,你应该看到上面的错误,比如"未定义window"。要解决此问题,请查找有问题的代码并a(如果定义了window,则在调用代码之前进行检查Gatsby正在构建时代码未运行(请参阅下面的代码示例(,或者b( 如果代码在React.js组件的render函数中,请移动该代码进入componentDidMount生命周期或CCD_ 11挂钩,这确保了代码不会运行,除非它在浏览器中。

因此,在不破坏钩子规则的情况下,在另一个钩子内部调用一个钩子,从而导致嵌套的无限循环。在调用document之前,您需要确保它的创建。只需添加一个检查条件:

import { useState } from 'react';
const getItem = (key) => {
if (typeof document !== undefined) {
document.cookie.split(`; `).reduce((total, currentCookie) => {
const item = currentCookie.split(`=`);
const storedKey = item[0];
const storedValue = item[1];
return key === storedKey ? decodeURIComponent(storedValue) : total;
}, ``);
}
};
const setItem = (key, value, numberOfDays) => {
const now = new Date();
// set the time to be now + numberOfDays
now.setTime(now.getTime() + numberOfDays * 60 * 60 * 24 * 1000);
if (typeof document !== undefined) {
document.cookie = `${key}=${value}; expires=${now.toUTCString()}; path=/`;
}
};
/**
*
* @param {String} key The key to store our data to
* @param {String} defaultValue The default value to return in case the cookie doesn't exist
*/
export const useCookie = (key, defaultValue) => {
const getCookie = () => getItem(key) || defaultValue;
const [cookie, setCookie] = useState(getCookie());
const updateCookie = (value, numberOfDays) => {
setCookie(value);
setItem(key, value, numberOfDays);
};
return [cookie, updateCookie];
};

由于您可能在document还不存在的组件或页面中调用useCookie自定义挂钩,我会使用相同的条件或使用具有空依赖关系的useEffect([],现在它不会打破挂钩规则(进行双重检查:

const Index = props => {
let cookie;
// both works
if (typeof document !== undefined) {
cookie = useCookie();
}
useEffect(() => {
cookie = useCookie();
}, []);
return <Layout>
<Seo title="Home" />
<h1>Hi people</h1>
</Layout>;
};

最新更新