【问题标题】:Object is possibly null error (typescript) when trying to display the value of an array which is stored in localstorage尝试显示存储在本地存储中的数组的值时,对象可能为空错误(打字稿)
【发布时间】:2020-07-20 17:55:01
【问题描述】:

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

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

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>
  );
};

它专门指向 lsOutput.innerHTML

我做错了什么? 我目前已将所有内容分配为 any 只是为了让它首先工作。 非常感谢您!

【问题讨论】:

    标签: javascript reactjs typescript eslint-config-airbnb react-tsx


    【解决方案1】:

    TypeScript 警告您 getElementById 可以返回 null(如果没有具有该 ID 的元素)。如果您知道该元素将存在,您可以放心使用带有non-null assertion 的 TypeScript:

    const lsOutput = document.getElementById('lsOutput')!;
    // −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−^
    

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

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

    const value: any = localStorage.getItem(key)!;
    // −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−^
    

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

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

    // Storing an array (or object)
    localStorage[key] = JSON.stringify(theArray);
    
    // Retrieving:
    const theArray = JSON.parse(localStorage[key]);
    

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

    相反,使用 React 方式:

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

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

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

    每次调用组件函数时不要去本地存储也可能有意义;也许在父组件中加载项目并将它们作为道具传递。

    【讨论】:

    • 非常感谢您抽出宝贵时间回复 T.J.克劳德。我强调太多试图做到这一点,最终只是盲目地盯着打字稿错误消息,没有意识到我应该以反应的方式来做事。我看到你起初相信我知道发生了什么,我很抱歉我缺乏知识和奇怪的代码旋风导致你试图解决一些愚蠢的问题。
    • @jrwebbie - 完全不用担心,伙计!很高兴这有帮助。 :-)
    猜你喜欢
    • 1970-01-01
    • 2020-11-07
    • 2015-07-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多