diff --git a/src/useLocalStorage.test.tsx b/src/useLocalStorage.test.tsx
new file mode 100644
index 00000000..4b0a058d
--- /dev/null
+++ b/src/useLocalStorage.test.tsx
@@ -0,0 +1,23 @@
+/*
+Copyright 2025 New Vector Ltd.
+
+SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
+Please see LICENSE in the repository root for full details.
+*/
+
+import { test } from "vitest";
+import { render, screen } from "@testing-library/react";
+import { type FC, useEffect } from "react";
+
+import { setLocalStorageItem, useLocalStorage } from "./useLocalStorage";
+
+test("useLocalStorage reacts to changes made by an effect mounted on the same render", () => {
+ localStorage.clear();
+ const Test: FC = () => {
+ useEffect(() => setLocalStorageItem("my-value", "Hello!"), []);
+ const [myValue] = useLocalStorage("my-value");
+ return myValue;
+ };
+ render();
+ screen.getByText("Hello!");
+});
diff --git a/src/useLocalStorage.ts b/src/useLocalStorage.ts
index 1394e0d3..517c7c62 100644
--- a/src/useLocalStorage.ts
+++ b/src/useLocalStorage.ts
@@ -8,6 +8,8 @@ Please see LICENSE in the repository root for full details.
import EventEmitter from "events";
import { useCallback, useEffect, useState } from "react";
+import { useLatest } from "./useLatest";
+
type LocalStorageItem = ReturnType;
// Bus to notify other useLocalStorage consumers when an item is changed
@@ -20,13 +22,22 @@ export const useLocalStorage = (
const [value, setValue] = useState(() =>
localStorage.getItem(key),
);
+ const latestValue = useLatest(value);
useEffect(() => {
+ // We're about to set up the bus listener that will enable us to react to
+ // any future updates to the localStorage item. However, it's possible that
+ // we already missed an update if there was an effect which modified the
+ // item in the time *between* the render phase of useLocalStorage and the
+ // execution of this effect. Let's update the state if that happened.
+ const stored = localStorage.getItem(key);
+ if (latestValue.current !== stored) setValue(stored);
+
localStorageBus.on(key, setValue);
return (): void => {
localStorageBus.off(key, setValue);
};
- }, [key, setValue]);
+ }, [key, latestValue, setValue]);
return [
value,