Skip to content

Commit

Permalink
fix(history, queryString): downgrade history to 4.x, added `createQue…
Browse files Browse the repository at this point in the history
…ryString` for current values and arbitrary values.
  • Loading branch information
BowlingX committed Dec 4, 2019
1 parent 2cccb03 commit 04e0899
Show file tree
Hide file tree
Showing 6 changed files with 96 additions and 357 deletions.
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@
"query-string": "^6.9.0"
},
"peerDependencies": {
"history": "^5",
"history": "^4",
"immer": "^5",
"react": ">=16.8",
"react-dom": ">=16.8",
Expand All @@ -79,7 +79,7 @@
"enzyme-adapter-react-16": "^1.15.1",
"expect": "^24.9.0",
"gh-pages": "^2.1.1",
"history": "^5.0.0-beta.0",
"history": "^4.10.1",
"immer": "^5.0.0",
"jest": "^24.9.0",
"codecov": "^3.5.0",
Expand Down
2 changes: 1 addition & 1 deletion src/examples/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* tslint:disable:no-expression-statement no-object-mutation */
import { createBrowserHistory } from 'history'
import React, { memo } from 'react'
import React from 'react'
import Geschichte, { factoryParameters, pm, serializers } from '../index'

const history = createBrowserHistory()
Expand Down
53 changes: 25 additions & 28 deletions src/lib/middleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -177,35 +177,32 @@ export const immerWithPatches = config => (set, get, api) =>

export const converter = (historyInstance: History) => (set, get) => {
const initialQueries = parse(historyInstance.location.search)
const unregisterListener = historyInstance.listen(
// @ts-ignore
({ location, action }) => {
// don't handle our own actions
if (
action === 'PUSH' ||
(action === 'REPLACE' && location.state && location.state.__g__)
) {
return
}
const nextQueries = parse(location.search)
const namespaces = get().namespaces
Object.keys(namespaces).forEach(ns => {
set(
state => {
state.query = applyFlatConfigToState(
state.mappedConfig,
nextQueries,
ns,
state.values,
state.initialValues
)
},
HistoryEventType.REGISTER,
ns
)
})
const unregisterListener = historyInstance.listen((location, action) => {
// don't handle our own actions
if (
action === 'PUSH' ||
(action === 'REPLACE' && location.state && location.state.__g__)
) {
return
}
)
const nextQueries = parse(location.search)
const namespaces = get().namespaces
Object.keys(namespaces).forEach(ns => {
set(
state => {
state.query = applyFlatConfigToState(
state.mappedConfig,
nextQueries,
ns,
state.values,
state.initialValues
)
},
HistoryEventType.REGISTER,
ns
)
})
})
return {
/** batch pushes the given namespaces */
batchPushState: (ns: readonly string[], fn) => {
Expand Down
28 changes: 20 additions & 8 deletions src/lib/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import { History } from 'history'
import LocationState = History.LocationState

import { stringify } from 'query-string'
import {
createContext,
useCallback,
Expand All @@ -17,11 +18,10 @@ import {
converter,
historyManagement,
immerWithPatches,
NamespaceValues,
StoreState
} from './middleware'
import { Serializer } from './serializers'
import { flattenConfig } from './utils'
import { createQueryObject, flattenConfig } from './utils'

export const DEFAULT_NAMESPACE = 'default'

Expand Down Expand Up @@ -57,9 +57,10 @@ export const geschichte = (historyInstance: History<LocationState>) => {
export const factoryParameters = <T = object>(
config: Config,
// tslint:disable-next-line:no-object-literal-type-assertion
initialState: T = {} as T,
initialValues: T = {} as T,
ns: string = DEFAULT_NAMESPACE
) => {
const flatConfig = flattenConfig(config)
const useQuery = () => {
const [useStore, api] = useContext(StoreContext) as [
UseStore<StoreState<T>>,
Expand All @@ -77,11 +78,9 @@ export const factoryParameters = <T = object>(
)
const { register, pushState, replaceState } = useStore(callback)

const flatConfig = useMemo(() => flattenConfig(config), [config])

useMemo(() => {
register(config, flatConfig, ns, initialState)
}, [flatConfig])
register(config, flatConfig, ns, initialValues)
}, [])

const initialNamespaceValues = useStore(state => state.namespaces[ns])
// initial state
Expand Down Expand Up @@ -113,6 +112,15 @@ export const factoryParameters = <T = object>(

return useMemo(
() => ({
createQueryString: (values?: object) =>
stringify(
createQueryObject(
flatConfig,
ns,
values || innerValues.values,
innerValues.initialValues
)
),
initialValues: innerValues.initialValues,
pushState: (state: (state: T) => void) => pushState(ns, state),
replaceState: (state: (state: T) => void) => replaceState(ns, state),
Expand All @@ -121,5 +129,9 @@ export const factoryParameters = <T = object>(
[innerValues, pushState, replaceState]
)
}
return { useQuery }

const createQueryString = (values: T) =>
stringify(createQueryObject<T>(flatConfig, ns, values, initialValues))

return { useQuery, createQueryString }
}
31 changes: 30 additions & 1 deletion src/lib/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,10 @@ export const formatNamespace = (key: string, ns?: string) => {
return ns && ns !== DEFAULT_NAMESPACE ? `${ns}.${key}` : key
}

export const get = (object: object, path: ReadonlyArray<string | number>) => {
export const get = <T = object>(
object: T,
path: ReadonlyArray<string | number>
) => {
return path.reduce((next, key) => {
return next[key]
}, object)
Expand All @@ -38,6 +41,7 @@ export const get = (object: object, path: ReadonlyArray<string | number>) => {
* Default skip implementation
*/
export const skipValue = (value?: any, initialValue?: any) =>
value === undefined ||
value === null ||
shallowEqual(value, initialValue) ||
(Array.isArray(value) && value.length === 0)
Expand Down Expand Up @@ -79,6 +83,31 @@ export const createQueriesFromPatch = (
}, {})
}

/**
* Creates a queryObject that can be serialized.
*/
export const createQueryObject = <T = object>(
config: MappedConfig,
ns: string,
values: T,
initialState: T
) => {
return Object.keys(config).reduce((next, parameter) => {
const { path, serializer } = config[parameter]
const possibleValue = get(values, path)
const nextValue = skipValue(possibleValue, get(initialState, path))
? undefined
: possibleValue
if (nextValue === undefined) {
return next
}
return {
...next,
[formatNamespace(parameter, ns)]: serializer.serialize(nextValue)
}
}, {})
}

export const applyDiffWithCreateQueriesFromPatch = (
config: Config,
ns: string,
Expand Down
Loading

0 comments on commit 04e0899

Please sign in to comment.