Skip to content

Commit

Permalink
Introduce usePage and useSuperglue hooks.
Browse files Browse the repository at this point in the history
These are lightweight wrappers around Redux's `useSelector` and a nice, but
must have convenience as we move away from `mapStateToProps`.
  • Loading branch information
jho406 committed Oct 14, 2024
1 parent 38e3d6e commit 9fc633a
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 0 deletions.
1 change: 1 addition & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ nav:
- Reference:
- Rails Utilities: rails-utils.md
- Page utilities: functions-passed.md
- Hooks: reference/hooks.md
- Nav: reference/components.Nav.md
- Superglue: reference/index.md
- Types: reference/types.md
Expand Down
19 changes: 19 additions & 0 deletions superglue/lib/hooks/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { useSelector } from 'react-redux'
import { Page, RootState, SuperglueState } from '../types'

/**
* A lightweight hook that grabs the superglue state from the store.
*/
export function useSuperglue() {
return useSelector<RootState, SuperglueState>((state) => state.superglue)
}

/**
* A lightweight hook that grabs the current page from the store.
*/
export function usePage() {
const superglueState = useSuperglue()
const currentPageKey = superglueState.currentPageKey

return useSelector<RootState, Page>((state) => state.pages[currentPageKey])
}
1 change: 1 addition & 0 deletions superglue/lib/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ import {
export { fragmentMiddleware } from './middleware'
export { getIn } from './utils/immutability'
export { urlToPageKey }
export { usePage, useSuperglue } from './hooks'

function pageToInitialState(key: string, page: VisitResponse) {
const slices = page.slices || {}
Expand Down
73 changes: 73 additions & 0 deletions superglue/spec/lib/hooks.spec.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import { renderHook } from '@testing-library/react'
import { usePage, useSuperglue } from '../../lib'
import { describe, it } from 'vitest'
import { Provider } from 'react-redux'
import { configureStore } from '@reduxjs/toolkit'

describe('hooks', () => {
describe('useSuperglue', () => {
it('returns the superglue state', () => {
const preloadedState = {
superglue: {
currentPageKey: '/current?abc=123',
pathname: '/current',
search: '?abc=123',
csrfToken: 'csrf123',
assets: ['js-asset-123'],
},
}

let store = configureStore({
preloadedState,
reducer: (state) => state,
})
const wrapper = ({ children }) => (
<Provider store={store}>{children}</Provider>
)
const { result } = renderHook(() => useSuperglue(), { wrapper })

expect(result.current).toEqual(preloadedState.superglue)
})
})

describe('usePage', () => {
it('returns the page state', () => {
const preloadedState = {
superglue: {
currentPageKey: '/current?abc=123',
pathname: '/current',
search: '?abc=123',
csrfToken: 'csrf123',
assets: ['js-asset-123'],
},
pages: {
'/current?abc=123': {
data: {
heading: 'selected',
},
},
'/other': {
data: {
heading: 'not selected',
},
},
},
}

let store = configureStore({
preloadedState,
reducer: (state) => state,
})
const wrapper = ({ children }) => (
<Provider store={store}>{children}</Provider>
)
const { result } = renderHook(() => usePage(), { wrapper })

expect(result.current).toEqual({
data: {
heading: 'selected',
},
})
})
})
})
1 change: 1 addition & 0 deletions superglue/typedoc.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"entryPoints": [
"./lib/index.tsx",
"./lib/types/index.ts",
"./lib/hooks/index.ts",
"./lib/types/requests.ts",
"./lib/components/Nav.tsx"
],
Expand Down

0 comments on commit 9fc633a

Please sign in to comment.