Last active
August 22, 2019 15:39
-
-
Save dance2die/07659aef6b54ed1305bb67f7fe88498d to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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