Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
import React, { createContext, useContext, useReducer } from "react";
// 1️⃣
const initialState = {
containerRef: null,
stickyRefs: new Map(),
};
// No operation
const noop = () => {};
// 2️⃣
const initialDispatch = {
setContainerRef: noop,
addStickyRef: noop
};
const StickyStateContext = createContext(initialState);
const StickyDispatchContext = createContext(initialDispatch);
const ActionType = {
setContainerRef: "set container ref",
addStickyRef: "add sticky ref",
};
// 3️⃣
function reducer(state, action) {
const { type, payload } = action;
switch (type) {
case ActionType.setContainerRef:
// Reassigning a new ref, will infinitely re-load!
return Object.assign(state, {
containerRef: { current: payload.containerRef }
});
case ActionType.addStickyRef:
const { topSentinelRef, bottomSentinelRef, stickyRef } = payload;
state.stickyRefs.set(topSentinelRef.current, stickyRef);
state.stickyRefs.set(bottomSentinelRef.current, stickyRef);
return Object.assign(state, {
stickyRefs: state.stickyRefs
});
default:
return state;
}
}
// 4️⃣
function StickyProvider({ children }) {
const [state, dispatch] = useReducer(reducer, initialState);
const setContainerRef = containerRef =>
dispatch({ type: ActionType.setContainerRef, payload: { containerRef } });
const addStickyRef = (topSentinelRef, bottomSentinelRef, stickyRef) =>
dispatch({
type: ActionType.addStickyRef,
payload: { topSentinelRef, bottomSentinelRef, stickyRef }
});
// 5️⃣
const actions = { setContainerRef, addStickyRef };
return (
<StickyStateContext.Provider value={state}>
<StickyDispatchContext.Provider value={actions}>
{children}
</StickyDispatchContext.Provider>
</StickyStateContext.Provider>
);
}
// 6️⃣
function useStickyState() {
const context = useContext(StickyStateContext);
if (context === undefined)
throw Error('"useStickyState should be used under "StickyStateContext');
return context;
}
// 7️⃣
function useStickyActions() {
const context = useContext(StickyDispatchContext);
if (context === undefined)
throw Error(
'"useStickyActions should be used under "StickyDispatchContext'
);
return context;
}
const initialSectionValues = {
topSentinelRef: null,
bottomSentinelRef: null
};
// 8️⃣
const StickySectionContext = createContext(initialSectionValues);
export {
StickyProvider,
useStickyState,
useStickyActions,
ActionType,
StickySectionContext
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.