Invalid hook call при работе с localStorage

214
30 июня 2022, 00:40

Имеется 3 файла:

  1. Основной компонент
  2. Файл со стейтами, которые забиваются в локальное хранилище
  3. Файл с функцией-ресетом для сброса этих самых стейтов в дефлотные значения

Я импотрирую файл со стейтами в основной компонент и всё ок, но когда я импортирую файл с функцией-ресетом, получаю ошибку "Error: Invalid hook call. Hooks can only be called inside of the body of a function component. "

Почитал документацию по реакту, но понимания ошибки не пришло

  1. Код первого файла
import React from 'react';
import { LocalStorage } from './components/localStorageList'
import { resetLocalStorage } from './components/resetLocalStorage'
function mainComponent() {
    const localState = LocalStorage(); // local storage keys
    const resetState = () => resetLocalStorage(); // reset local storate states
    return (
        <div>
            <button onClick={() => resetState()}>
                 {svgRefreshPage}
           </button>
       </div>
    )
}
  1. Код второго файла
import { useState, useEffect } from 'react';
const useLocalStorageList = (key, defaultValue) => {
    const stored = localStorage.getItem(key);
    const initial = stored ? JSON.parse(stored) : defaultValue;
    const [value, setValue] = useState(initial);
    useEffect(() => {
        localStorage.setItem(key, JSON.stringify(value));
    }, [key, value]);
    return [value, setValue];
};
//local storage keys
export const LocalStorage = () => {
    const [localStorageState, setLocalStorageState] = useLocalStorageList('Timer time', 1800)
    return {localStorageState, setLocalStorageState}
}
  1. Код третьего файла
import { LocalStorage } from './localStorageList'
const localState = LocalStorage(); //local storage keys
export const resetLocalStorage = () => {
    localState.setTimerValue(1800)
}

Ссылка на sandbox

Answer 1
const localState = LocalStorage(); //local storage keys

Этот вызов кривой. Он вообще вне компонента.

Answer 2

У хуков есть ограничения, на то, где их можно вызывать:

  1. непосредственно внутри функции компонента
  2. непосредственно внутри другого хука

Также рекомендуют называть их начиная с use, эта договоренность позволяет реакту проверять правильность вызова и пользовательских хуков.

В коде в вопросе, вызов хука LocalStorage в третьем файле происходит вне компонента либо другого хука, отсюда и ошибки.

Кроме того, в данном случае нет смысла разделять действия над хранилищем на два файла, и достаточно просто объявить метод reset внутри LocalStorage, в этом случае код может выглядеть так:

export const LocalStorage = () => {
  const [localStorageState, setLocalStorageState] = useLocalStorageList(
    "State",
    "Default Value"
  );
  const resetLocalStorageState = () => {
    setLocalStorageState("Default Value");
  };
  return [localStorageState, setLocalStorageState, resetLocalStorageState];
};

И в использовании

function App() {
  const [value, update, reset] = LocalStorage(); // local storage keys
  return (
    <div>
      <button onClick={reset}>Refresh State to default</button>
      <br />
      <button onClick={() => update("State was changed")}>Change State</button>
      <p>{value}</p>
    </div>
  );
}

Пример в песочнице: https://codesandbox.io/s/amazing-feather-1mtgg?file=/src/localState.jsx

READ ALSO
Выполнение параллельных запросов при обращение к API (AXIOS, JS)

Выполнение параллельных запросов при обращение к API (AXIOS, JS)

Разрабатываю приложение на JS и есть необходимость обращения к api для получения записейНо Api накладывает ограничение на количество одновременно...

255
Оператор JavaScript, похожий на SQL &#171;NOT LIKE&#187;

Оператор JavaScript, похожий на SQL «NOT LIKE»

Как записать not like в следующем условии? В данном условии приведен просто like

163
Некорректная работа js в FireFox

Некорректная работа js в FireFox

Есть скрипт, который подставляет номер дома из выпадающего списка в TextBox , из которого будет сохранен в БДПосле сохранения адреса, при заходе...

221
Как обособить значения строкового массива?

Как обособить значения строкового массива?

Есть строковый массив из 7 значенийПри вводе числа система выдаёт день недели

251