Gatsbyjs & localStorage:持久化状态
Posted
技术标签:
【中文标题】Gatsbyjs & localStorage:持久化状态【英文标题】:Gatsbyjs & localStorage: Persisting state 【发布时间】:2021-05-20 16:30:54 【问题描述】:我正在为我的网站制作 GDPR 横幅。我希望这个横幅出现在我网站的每个页面上,直到用户单击接受按钮。在我的 Gatsby 站点中,我使用 Context API 来存储用户是否已接受条款,并在本地存储中使用一种称为 GDPR_Accepted 的状态。我将其初始化为 false,当用户单击 GDPR 横幅中的接受按钮时,我将其切换为 true。设置为 true 后,GDPR 横幅不应显示在任何页面上。
我可以使用此功能,除非用户离开我的网站并返回 GDPR_Accepted 重置为 false,并且即使用户之前已接受条款,GDPR 横幅也会再次显示。为什么用户离开时 localStorage 不持久化数据?
这是我处理 GDPR_Accepted 状态的上下文 API 代码:
function reducer(state, action)
switch(action.type)
case TOGGLE_GDPR:
return
...state,
GDPR: state.GDPR === false ? true : false
default:
return
...state
export const GlobalContextProvider = ( children ) =>
const [state, dispatch] = React.useReducer(reducer, initialState)
useEffect(() =>
if (storageAvailable('localStorage'))
localStorage.setItem('GDPR_Accepted', state.GDPR)
else
return 0;
, [state])
return (
<GlobalStateContext.Provider value=state>
<GlobalDispatchContext.Provider value=dispatch>
children
</GlobalDispatchContext.Provider>
</GlobalStateContext.Provider>
)
我还从 MDN 文档中获取了这个功能,首先检查本地存储是否可用:
// Checks if localStorage is available in the user's browser
function storageAvailable(type)
var storage;
try
storage = window[type];
var x = '__storage_test__';
storage.setItem(x, x);
storage.removeItem(x);
return true;
catch(e)
return e instanceof DOMException && (
// everything except Firefox
e.code === 22 ||
// Firefox
e.code === 1014 ||
// test name field too, because code might not be present
// everything except Firefox
e.name === 'QuotaExceededError' ||
// Firefox
e.name === 'NS_ERROR_DOM_QUOTA_REACHED') &&
// acknowledge QuotaExceededError only if there's something already stored
(storage && storage.length !== 0);
在我的前端,我有一个显示实际出现的 GDPR 横幅的组件,在此组件中,我使用以下命令切换存储在 localStorage 中的 GDPR_Accepted 状态:
<Button className=styles.acceptButton onClick=async () =>
dispatch( type: "TOGGLE_GDPR" )
>Accept All Cookies</Button>
然后,在我的 Layout 组件中,我使用三元组来决定是否应该显示 GDPR 横幅。我从 Context API const state = useContext(GlobalStateContext);
访问状态,然后使用三元:
state.GDPR === false ?
<GDPR />
: null
所有这些都有效,但是当用户离开和回来时,我遇到了保持状态的问题。我想到的一些可能的问题:
Gatsby 使用服务器端渲染,语言内置的许多 javascript 对象(如window
甚至localStorage
)在 Gatsby 构建时由于 s-s-r 会引发错误。我使用localStorage
时没有这个问题,这很奇怪。
localStorage
应该只存储 strings,但是当我将 strings 存储在 localStorage
中时,我的 GDPR 横幅无法正常工作。如果我使用 boolean,我只能让它工作。出于某种原因,booleans 有效,但 strings 无效。
我正在使用 context 并且它是决定是否显示横幅的状态,我应该直接检查localStorage
吗?如果有,怎么做?
【问题讨论】:
【参考方案1】:看起来您在 GlobalContextProvider 定义中的 useEffect
挂钩正在重置 localStorage 键的值。每次安装组件(即每次页面加载)时,此功能将(至少)运行。无需在每次页面加载时初始化 localStorage 键。您调用setItem
的唯一位置应该是按钮的onClick
。
【讨论】:
以上是关于Gatsbyjs & localStorage:持久化状态的主要内容,如果未能解决你的问题,请参考以下文章