Skip to content

Instantly share code, notes, and snippets.

@wchargin
Last active August 29, 2023 07:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wchargin/aa15c01909e613eaa0c693be11f4b615 to your computer and use it in GitHub Desktop.
Save wchargin/aa15c01909e613eaa0c693be11f4b615 to your computer and use it in GitHub Desktop.
telescroll: trigger a scroll event in the future
import { createContext, useContext, useRef } from "react";
const TelescrollContext = createContext({
provideScroll: () => {},
requestScroll: () => {},
});
export function TelescrollProvider({ children }) {
const requested = useRef(null);
function provideScroll(key) {
return (el) => {
if (requested.current === key) {
el.scrollIntoView();
requested.current = null;
}
};
}
function requestScroll(key) {
if (typeof key !== "string") throw new Error("Invalid scroll key: " + key);
requested.current = key;
// TODO: When/how can we unregister a scroll that isn't triggered?
}
return (
<TelescrollContext.Provider value={{ provideScroll, requestScroll }}>
{children}
</TelescrollContext.Provider>
);
}
export function useTelescroll() {
return useContext(TelescrollContext);
}
// A detail page for an item, including a link back to the main page. The main
// page has very many items, so we'd like to load it and scroll so that the
// view includes the item that we just came from. Use `requestScroll`.
function DetailPage({ id }) {
const { requestScroll } = useTelescroll();
return (
<main>
<h1>Item details</h1>
<p>...</p>
<Link to="/" onClick={() => requestScroll(`item-${id}`)}>
Back to main page
</Link>
</main>
);
}
// A main page, with many item overviews. Each uses `provideScroll` to allow
// other pages to scroll into it.
function MainPage() {
const { provideScroll } = useTelescroll();
const items = getAllTheItems();
return (
<main>
<h1>All the items</h1>
{items.map((item) => (
<div key={item.id} ref={provideScroll(`item-${id}`)}>
<h2>Item #{item.id}</h2>
<p>{item.description}</p>
<p>
<Link to={`/item/${item.id}`}>More details&hellip;</Link>
</p>
</div>
))}
</main>
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment