facebookexperimental/Recoil

<RecoilURLSync doesn't throttle calls to history.replace / history.pushState w/ Safari

Open

#1910 opened on Jul 16, 2022

View on GitHub
 (1 comment) (0 reactions) (0 assignees)JavaScript (19,428 stars) (1,151 forks)batch import
help wanted

Description

With Safari, if you call history.replace or history.pushState too frequently, the history APIs will throw a SecurityError.

SecurityError: Attempt to use history.replaceState() more than 100 times per 30 seconds

example code to reproduce:

import * as React from "react";
import ReactDOM from "react-dom/client";
import { RecoilRoot, atom, useRecoilState } from "recoil";
import { RecoilURLSyncJSON, syncEffect } from "recoil-sync";
import { string } from "@recoiljs/refine";

const textState = atom({
  key: "textState", // unique ID (with respect to other atoms/selectors)
  default: "", // default value (aka initial value)
  effects: [syncEffect({ refine: string() })],
});

function TextInput() {
  const [text, setText] = useRecoilState(textState);

  const onChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    setText(event.target.value);
  };

  return (
    <div>
      <input type="text" value={text} onChange={onChange} />
      <br />
      Echo: {text}
    </div>
  );
}

export default function App() {
  return (
    <div>
      <TextInput />;
    </div>
  );
}

const root = ReactDOM.createRoot(document.getElementById("root")!);
root.render(
  <React.StrictMode>
    <RecoilRoot>
      <RecoilURLSyncJSON location={{ part: "queryParams" }}>
        <App />
      </RecoilURLSyncJSON>
    </RecoilRoot>
  </React.StrictMode>
);

Contributor guide