尝试从无状态 React 组件中的 localStorage 获取数据时出现 NodeInvocationException
NodeInvocationException when trying to get data from localStorage in stateless React component
我已经实现了这样的应用布局:
const Layout: React.SFC<IDefaultProps> = props => {
const { component: Component, ...rest } = props;
const logged = userServices.getUserLocalStorage();
return (
<Route
{...rest}
render={matchProps =>
logged != null ? (
<div className="container-fluid">
<NavMenuLogged {...matchProps} />
<div className="row wu-content">
<Component {...matchProps} />
</div>
<Footer />
</div>
) : (
<Redirect to="/" />
)
}
/>
);
};
希望将用户的登录信息保存在 localStorage 中,并从那里能够重定向用户登录;但我发现我无法访问 SFC 组件内的 localStorage。有人对此有解决方案吗? (优雅与否...)
这是 getUserLocalStorage() 函数:
export function getUserLocalStorage(){
let user:Utils.User = JSON.parse(localStorage.getItem("user") || '{}');
return user;
}
这是我得到的错误:
An unhandled exception occurred while processing the request.
NodeInvocationException: localStorage is not defined
ReferenceError: localStorage is not defined
at Object.getUserLocalStorage [as b] (E:\Trabajo\...\ClientApp\dist\main-server.js:9138:27)
at Layout (E:\...\ClientApp\dist\main-server.js:38836:102)
at ReactCompositeComponentWrapper._constructComponentWithoutOwner (E:\...\ClientApp\dist\vendor.js:43899:14)
at ReactCompositeComponentWrapper._constructComponent (E:\...\ClientApp\dist\vendor.js:43875:19)
at ReactCompositeComponentWrapper.mountComponent (E:\...\ClientApp\dist\vendor.js:43778:21)
at Object.mountComponent (E:\...\ClientApp\dist\vendor.js:11753:35)
at ReactCompositeComponentWrapper.performInitialMount (E:\...\ClientApp\dist\vendor.js:43961:34)
at ReactCompositeComponentWrapper.mountComponent (E:\Trabajo\...\ClientApp\dist\vendor.js:43848:21)
at Object.mountComponent (E:\...\ClientApp\dist\vendor.js:11753:35)
at ReactDOMComponent.mountChildren (E:\...\ClientApp\dist\vendor.js:47391:44)
这与您设置应用程序的方式有关,当您调用 localStorage
时,它必须发生在客户端,而不是服务器端。作为节点,没有本地存储。
我会试试这个:
将其更改为 class 组件而不是使用功能组件,然后执行
componentDidMount(){
console.log(localStorage) // or whatever you need to do here.
}
如果您不想删除您的 SFC,您可以创建自己的 HOC,或使用像 recompose
这样的库。这是使用重构的代码片段:
const SFCWithLifeCycleHook = lifecycle({
componentDidMount() {
console.log(localStorage) //do something here...
}
})(SFC);
因为错误出现在服务端,在服务端渲染阶段,极有可能是Node环境中没有localStorage
导致的。 Node 中根本没有这样的东西,它是特定于浏览器的 API。所以该函数伪装地抛出一个 ReferenceError(可能是因为它是 ASP.NET,但我不确定)。
我假设无论如何都无法在服务器端呈现步骤中检索用户信息,并且这种特定情况下的用户数据仅存储在用户浏览器的本地存储中。在这种情况下,检查 localStorage
是否存在可能是有意义的,如果不存在,则 回退到默认值:
export function getUserLocalStorage(){
if (typeof localStorage === 'undefined') {
// will safely return if localStorage is not defined
return {};
}
let user:Utils.User = JSON.parse(localStorage.getItem("user") || '{}');
return user;
}
typeof •
适用于任何 •
,甚至是以前未定义的变量或引用。检查范围内是否存在某个引用是最安全的操作。
比较
if (localStorage) {
// will throw ReferenceError is localStorage is not defined
}
因为您可能不想在此时进行 client/server 代码拆分,所以 typeof
支持的检查可能是最佳选择。这样,您可以确保以下代码仅在 localStorage
引用可用的环境中 运行 (在大多数情况下,在浏览器的全局范围内)。您可能已经应用相同的做法来检查是否定义了 window
。
希望对您有所帮助!
我已经实现了这样的应用布局:
const Layout: React.SFC<IDefaultProps> = props => {
const { component: Component, ...rest } = props;
const logged = userServices.getUserLocalStorage();
return (
<Route
{...rest}
render={matchProps =>
logged != null ? (
<div className="container-fluid">
<NavMenuLogged {...matchProps} />
<div className="row wu-content">
<Component {...matchProps} />
</div>
<Footer />
</div>
) : (
<Redirect to="/" />
)
}
/>
);
};
希望将用户的登录信息保存在 localStorage 中,并从那里能够重定向用户登录;但我发现我无法访问 SFC 组件内的 localStorage。有人对此有解决方案吗? (优雅与否...)
这是 getUserLocalStorage() 函数:
export function getUserLocalStorage(){
let user:Utils.User = JSON.parse(localStorage.getItem("user") || '{}');
return user;
}
这是我得到的错误:
An unhandled exception occurred while processing the request.
NodeInvocationException: localStorage is not defined
ReferenceError: localStorage is not defined
at Object.getUserLocalStorage [as b] (E:\Trabajo\...\ClientApp\dist\main-server.js:9138:27)
at Layout (E:\...\ClientApp\dist\main-server.js:38836:102)
at ReactCompositeComponentWrapper._constructComponentWithoutOwner (E:\...\ClientApp\dist\vendor.js:43899:14)
at ReactCompositeComponentWrapper._constructComponent (E:\...\ClientApp\dist\vendor.js:43875:19)
at ReactCompositeComponentWrapper.mountComponent (E:\...\ClientApp\dist\vendor.js:43778:21)
at Object.mountComponent (E:\...\ClientApp\dist\vendor.js:11753:35)
at ReactCompositeComponentWrapper.performInitialMount (E:\...\ClientApp\dist\vendor.js:43961:34)
at ReactCompositeComponentWrapper.mountComponent (E:\Trabajo\...\ClientApp\dist\vendor.js:43848:21)
at Object.mountComponent (E:\...\ClientApp\dist\vendor.js:11753:35)
at ReactDOMComponent.mountChildren (E:\...\ClientApp\dist\vendor.js:47391:44)
这与您设置应用程序的方式有关,当您调用 localStorage
时,它必须发生在客户端,而不是服务器端。作为节点,没有本地存储。
我会试试这个: 将其更改为 class 组件而不是使用功能组件,然后执行
componentDidMount(){
console.log(localStorage) // or whatever you need to do here.
}
如果您不想删除您的 SFC,您可以创建自己的 HOC,或使用像 recompose
这样的库。这是使用重构的代码片段:
const SFCWithLifeCycleHook = lifecycle({
componentDidMount() {
console.log(localStorage) //do something here...
}
})(SFC);
因为错误出现在服务端,在服务端渲染阶段,极有可能是Node环境中没有localStorage
导致的。 Node 中根本没有这样的东西,它是特定于浏览器的 API。所以该函数伪装地抛出一个 ReferenceError(可能是因为它是 ASP.NET,但我不确定)。
我假设无论如何都无法在服务器端呈现步骤中检索用户信息,并且这种特定情况下的用户数据仅存储在用户浏览器的本地存储中。在这种情况下,检查 localStorage
是否存在可能是有意义的,如果不存在,则 回退到默认值:
export function getUserLocalStorage(){
if (typeof localStorage === 'undefined') {
// will safely return if localStorage is not defined
return {};
}
let user:Utils.User = JSON.parse(localStorage.getItem("user") || '{}');
return user;
}
typeof •
适用于任何 •
,甚至是以前未定义的变量或引用。检查范围内是否存在某个引用是最安全的操作。
比较
if (localStorage) {
// will throw ReferenceError is localStorage is not defined
}
因为您可能不想在此时进行 client/server 代码拆分,所以 typeof
支持的检查可能是最佳选择。这样,您可以确保以下代码仅在 localStorage
引用可用的环境中 运行 (在大多数情况下,在浏览器的全局范围内)。您可能已经应用相同的做法来检查是否定义了 window
。
希望对您有所帮助!