web-dev-qa-db-ja.com

ReactフックでlocalStorageが空かどうかを確認する方法は?

これは私が尋ねた別の質問の続きです ボタンを使用してローカルブラウザストレージにデータを追加/削除し、UIテーブルに表示します(React)

LocalStorageをチェックし、エミッターを使用して、localStorageの値が空かどうかをコンソールに通知しようとしています。

2つの問題があると思います。

  1. アプリは、初期化時に(ブラウザーを開いたときに)localStorageを確認する必要があります
  2. 値が追加または削除されるたびにlocalStorageがチェックされるように、useStateを使用する必要があります

以下は私の試みです(index.js):

_import React,{useState} from 'react';
import ReactDOM from 'react-dom';
const EventEmitter = require('events');

const useStateWithLocalStorageArray = localStorageKey => {
  const [value, setValue] = React.useState(
    JSON.parse(localStorage.getItem(localStorageKey) || '[]' )
  );
  React.useEffect(() => {
    localStorage.setItem(localStorageKey, JSON.stringify(value))
  }, [value]);
  return [value, setValue];
};

const checkLocalStorage = function() {
  const myEmitter = new EventEmitter();
  myEmitter.on('event', () => {
    if (localStorage.getItem('customKey1') === '[]') {
      console.log('Local storage is empty');
    }
  });
  return myEmitter.emit('event');
}

const App =()=>{
  const [items,setItems] = useStateWithLocalStorageArray('customKey1')
  const [value,setValue] = useState({NAME:'',AGE:'',SALARY:''})
  const [localValue, setLocalValue] = useState('')


  const updateValue = e =>{
     setValue({...value,[e.target.id]:e.target.value})
  }


  return(
    <div>
      <div>
        <input value={value.NAME} id='NAME' placeholder='Name' onChange={(e)=>updateValue(e)}/>
        <input value={value.AGE } id='AGE' placeholder='Age' onChange={(e)=>updateValue(e)}/>
        <input value={value.SALARY} id='SALARY' placeholder='Salary' onChange={(e)=>updateValue(e)}/>
      <button onClick={()=>{
        setItems([...items,{...value}])
        setValue({NAME:'',AGE:'',SALARY:''})
        checkLocalStorage(setLocalValue)
        }}>ADD ITEM</button></div>

      <br/>
      <div>List of Items</div>
      <br/>
      { items &&
      <div>
        {
            items.map((item,index)=>(
              <li key={index}>{item.NAME}-{item.AGE}-{item.SALARY} <button onClick={()=>{
                setItems(items.filter((value,iindex) => iindex !== index))
                checkLocalStorage(setLocalValue)
              }}>Remove</button> </li>
            ))
        }
      </div>
    }
    </div>
  )
}

ReactDOM.render(<App/>, document.getElementById('root'));
_

値が追加または削除されるたびに呼び出される関数checkLocalStorage()を作成しました。

_const checkLocalStorage = function() {
  const myEmitter = new EventEmitter();
  myEmitter.on('event', () => {
    if (localStorage.getItem('customKey1') === '[]') {
      console.log('Local storage is empty');
    }
  });
  return myEmitter.emit('event');
}
_

しかし、期待どおりに機能していません。何が起こるか:

  1. Reactアプリを起動します(コンソールに「ローカルストレージが空です」と表示されていません))
  2. 値を送信すると、コンソールに「ローカルストレージが空です」と表示されます
  3. ブラウザを更新すると、「ローカルストレージが空です」というメッセージが消えます
  4. もう一度別の値を追加すると、同じプロセスが発生します。

何が起こるか(空のlocalStorageで始まる場合):

  1. Reactアプリを起動します(コンソールに「ローカルストレージは空です」と表示されています))
  2. 値(存在する値は1つのみ)を送信し、コンソールにメッセージを送信しません
  3. ページを更新してもコンソールメッセージが表示されない
  4. 値を削除すると、「ローカルストレージが空です」というメッセージがコンソールに表示される

Reactフックを適切に使用していないと思います。フックを初期化しました:

_const [localValue, setLocalValue] = useState('')
_

次に、_const App_内で次のように使用してみます。

_checkLocalStorage(setLocalValue)
_

前に言ったように、何が間違っているのかわかりません。フックを正しく使用していないと思います。詳細が必要な場合は、お知らせください。

1
W. Churchill

「onstorage」イベントを使用して、いつ更新されるかを確認できます。たとえば、アプリのルートで:

window.addEventListener('storage', event => {
  // event contains
  // key – the key that was changed
  // oldValue – the old value
  // newValue – the new value
  // url – 
  // storageArea – either localStorage or sessionStorage object where the update happened.
});
const useStorage = (storageName) => {

  const checkStorage = key => {
     const storedData = localStorage.getItem(key);
     if (!storedData) console.log('Local storage is empty');
  }

  useEffect(() => {
   // when app loaded
   checkStorage(storageName)

    // when storage updated
    const handler = ({key}) => checkStorage(key);
    window.addEventListener('storage', handler);
    retunr () => window.removeEventListener('storage', handler);
  }, []);
}
1