Возможно, объект имеет нулевую ошибку (машинопись) при попытке отобразить значение массива, который хранится в localstorage - PullRequest
0 голосов
/ 08 апреля 2020

В настоящее время я создаю приложение погоды, в котором вы можете хранить избранные местоположения, которые помещаются в массив, который, в свою очередь, сохраняется в localstorage.

Теперь я хочу отобразить значения массива в другом компоненте, но с моим кодом я все время спотыкаюсь об ошибке, что объект возможен 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.inner HTML

Что такое Я делаю не так? В настоящее время я назначил все как любое, чтобы попытаться заставить его работать первым. Заранее большое спасибо!

1 Ответ

2 голосов
/ 08 апреля 2020

TypeScript предупреждает вас, что getElementById может вернуть null (если нет элемента с таким идентификатором). Если вы знаете , что элемент будет существовать, вы успокаиваете TypeScript с утверждением non- null :

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

(но я не думаю, что вы это знаете, см. ниже в столбце.)

У вас будет такая же проблема позже с value. Анализ TypeScript не достаточно глубок, чтобы понять, что вы получаете key от localStorage.key(i), и поэтому вы знаете, 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]);

Вы пытаетесь работать напрямую с DOM в компоненте React, что редко требуется. Когда это необходимо, то, как вы это делаете, не является лучшей практикой (и не будет работать, если у вас уже нет другого элемента с идентификатором 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>
  );
};

Может также иметь смысл не go локальное хранилище каждый раз, когда вызывается функция компонента; возможно, загрузите элементы в родительский компонент и передайте их как реквизит.

...