尝试显示存储在本地存储中的数组的值时,对象可能为空错误(打字稿)

jrw*_*bie 2 javascript typescript reactjs eslint-config-airbnb react-tsx

我目前正在创建一个天气应用程序,您可以在其中存储您最喜欢的位置,这些位置被推送到数组中,而数组又存储在本地存储中。

现在,我想在不同的组件中显示数组的值,但在我的代码中,我不断地发现对象可能为空的错误。

export const FavoritesList: React.FC<any> = () => {
  // const storageFavorites = localStorage.getItem('favorites');
  const lsOutput = document.getElementById('lsOutput');
  for (let i = 0; i < localStorage.length; i++) {
    const key: any = localStorage.key(i);
    const value: any = localStorage.getItem(key);
    // console.log(value);
    value.forEach(
      (item: any) => (lsOutput.innerHTML += `<li>${item}</li><br/>`)
    );
  }
  return (
    <div>
      <ul id="lsOutput"></ul>
    </div>
  );
};
Run Code Online (Sandbox Code Playgroud)

它特别指向 lsOutput.innerHTML

我究竟做错了什么?我目前已将所有内容分配为任意,只是为了首先尝试使其工作。预先非常感谢您!

T.J*_*der 6

TypeScript 警告您getElementById可以返回null(如果没有具有该 ID 的元素)。如果您知道该元素将存在,您可以使用null断言来向 TypeScript 保证来向 TypeScript 保证:

\n\n
const lsOutput = document.getElementById(\'lsOutput\')!;\n// \xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92^\n
Run Code Online (Sandbox Code Playgroud)\n\n

(但我认为您不知道这一点,请参阅下面的栏下方。)

\n\n

稍后您将遇到同样的问题value。TypeScript 所做的分析不够深入,无法知道您key从中获得的信息localStorage.key(i),因此您知道 localStorage.getItem(key)将返回一个非-null值。再说一次,你必须告诉它:

\n\n
const value: any = localStorage.getItem(key)!;\n// \xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92^\n
Run Code Online (Sandbox Code Playgroud)\n\n

但还有另一个问题:value.forEach永远不会在该代码中定义。localStorage 存储字符串,不存储数组,并且字符串没有forEach

\n\n

当我想存储复杂的数据时localStorage,我使用 JSON。例如:

\n\n
// Storing an array (or object)\nlocalStorage[key] = JSON.stringify(theArray);\n\n// Retrieving:\nconst theArray = JSON.parse(localStorage[key]);\n
Run Code Online (Sandbox Code Playgroud)\n\n
\n\n

您尝试在 React 组件中直接使用 DOM,但这很少有必要。当有必要时,你这样做的方式不是最佳实践(并且不会工作,除非你已经有一个具有 ID 的不同lsOutput元素,在这种情况下,你正在创建一个带有无效值的 DOM结构——不能有两个相同的元素id值的元素)。当你的组件函数运行时,你从它返回的输出还不会出现在 DOM 中。

\n\n

相反,用 React 的方式来做:

\n\n
export const FavoritesList: React.FC<any> = () => {\n  const items = [];\n  for (let i = 0; i < localStorage.length; i++) {\n    const key: any = localStorage.key(i);\n    const value: any = localStorage.getItem(key);\n    items.push(value);\n  }\n  return (\n    <div>\n      <ul>{items.map(item => <li>{item}</li>}</ul>\n    </div>\n  );\n};\n
Run Code Online (Sandbox Code Playgroud)\n\n

我还建议使用单个存储条目来保存该项目数组,使用 JSON,如上所示:

\n\n
export const FavoritesList: React.FC<any> = () => {\n  const items: string[] = JSON.parse(localStorage.getItem("favorites"))!;\n  return (\n    <div>\n      <ul>{items.map(item => <li>{item}</li>}</ul>\n    </div>\n  );\n};\n
Run Code Online (Sandbox Code Playgroud)\n\n

每次调用组件函数时不访问本地存储也可能是有意义的;也许将项目加载到父组件中并将它们作为道具传递下来。

\n