当 React.js 中的 localStorage 发生任何变化时,如何立即更新状态

IT技术 javascript reactjs local-storage next.js
2021-05-02 01:10:37

localStorage myCart数组发生任何变化时,如何立即更新购物车页面数据下面是我的代码

const [cart, setCart] = React.useState([])

React.useEffect(() => {
    setCart(JSON.parse(localStorage.getItem('myCart')) || [])
}, [])

cart被更新时,页面重新加载,但不是在新项目中添加或更新任何现有的项目!

我怎样才能做到这一点,cart如果对“localStorage”进行任何更改,它会立即更新?

提前致谢。

3个回答

您可以事件添加事件侦听器localstorage

React.useEffect(() => {
    
window.addEventListener('storage', () => {
  // When local storage changes, dump the list to
  // the console.
   setCart(JSON.parse(localStorage.getItem('myCart')) || [])   
});

   
}, [])

Window 接口的 storage 事件在存储区域(localStorage)被修改时触发。 storage 事件仅在非自身的窗口进行更改时触发。

.

我认为这是处理这种情况的更好方法。这就是我处理这种情况的方式。

在你的组件中,

const [cart, setCart] = useState([]);

React.useEffect(() => {
    async function init() {
      const data = await localStorage.getItem('myCart'); 
      setCart(JSON.parse(data));
    }
    init();
}, [])

页面重新加载时会更新购物车,但不会在新项目添加或更新任何现有项目时更新!

我怎样才能做到这一点,如果对“localStorage”进行任何更改,购物车会立即更新?

添加项目时,假设您有一个方法 addItem()

async function addItem(item) {
  // Do not update local-storage, instead update state
  await setState(cart => cart.push(item));
}

现在添加另一个useEffect();

useEffect(() => {
 localstorage.setItem('myCart', cart);
}, [cart])

现在,当购物车状态更改时,它将保存到本地存储

addEventListener在存储上不是一件好事。每次存储更改时,在您的代码中,您都必须获取项目并解析它,这需要几毫秒才能完成,这会导致 UI 更新变慢。

在react中,

  1. 首先从localstorage/加载数据database并初始化状态。
  2. 然后根据需要更新代码中的状态。
  3. 然后监听状态更改以执行任何任务(在这种情况下保存到 localstorage )

如果您的addItem()函数是上述组件(cart 组件)的子项,那么您可以将setItem函数作为 prop /传递,或者您可以使用 contex API 或使用 Redux

更新

如果addCart是另一个组件

  1. 如果具有addCart功能的组件是cart组件的子组件,请使用props- https://reactjs.org/docs/components-and-props.html
  2. 如果具有addCart功能的组件不是组件的子cart组件,则使用上下文 api 在组件之间进行通信 - https://reactjs.org/docs/context.html
  3. 如果您想以干净和更好的方式管理数据,请使用https://redux.js.org/

根据用例,我假设您addItemProduct组件中声明函数..

我建议您使用 Redux 来处理这种情况。

更新

正如@Matt Morgan 在评论部分所说,使用上下文 API 更适合这种情况。

但是如果你的应用程序很大(我假设你正在构建一个电子商务系统),最好使用像 Redux 这样的状态管理系统。对于这种情况,上下文 API 就足够了

我遵循了@Shubh上面给出的答案

当从本地存储中删除现有值或同一浏览器中的另一个窗口更新本地存储中正在使用的值时,它会起作用。例如,当单击同一窗口中的按钮更新本地存储时,它不起作用。

下面的代码也处理这个问题。它可能看起来有点多余,但它有效:

        const [loggedInName, setLoggedInName] = useState(null);
        
        useEffect(() => {
            setLoggedInName(localStorage.getItem('name') || null)
            window.addEventListener('storage', storageEventHandler, false);
        }, []);
        
        function storageEventHandler() {
            console.log("hi from storageEventHandler")
            setLoggedInName(localStorage.getItem('name') || null)
        }
    
        function testFunc() {
        localStorage.setItem("name", "mayur1234");
        storageEventHandler();
    }



return(
<div>
  <div onClick={testFunc}>TEST ME</div>
</div>
)

编辑:

我还发现使用一个组件中的隐藏按钮来执行此操作的坏方法,单击该按钮将从 localStorage 获取值并将其设置在当前组件中。

这个隐藏的按钮可以被赋予一个 id,并可以从任何其他使用普通 JS 的组件调用

例如: document.getElementById("hiddenBtn").click()

https://stackoverflow.com/a/69222203/9977815详细信息