Skip to content

Commit

Permalink
fix: fixed stale / wrong states when initializing
Browse files Browse the repository at this point in the history
  • Loading branch information
BowlingX committed May 6, 2022
1 parent b3ab314 commit 040db01
Show file tree
Hide file tree
Showing 7 changed files with 117 additions and 86 deletions.
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -101,10 +101,10 @@
"npm-run-all": "^4.1.5",
"open-cli": "^7.0.1",
"prettier": "^2.6.1",
"react": "^18.0.0",
"react": "^18.1.0",
"jsdom-global": "^3.0.2",
"react-docgen-typescript-loader": "^3.7.2",
"react-dom": "^18.0.0",
"react-dom": "^18.1.0",
"semantic-release": "^19.0.2",
"trash-cli": "^5.0.0",
"ts-jest": "^27.1.4",
Expand Down
64 changes: 8 additions & 56 deletions src/__tests__/defaults.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,60 +2,12 @@
import { render, cleanup, screen } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import { createMemoryHistory } from 'history'
import React, {
createContext,
FC,
useCallback,
useContext,
useMemo,
useState,
} from 'react'
import Geschichte, { factoryParameters, pm, serializers } from '../index'

const config = {
someParameter: pm('wow', serializers.string),
}
const defaultValues = () => ({
someParameter: 'test',
})

interface Props<T = {}> {
readonly defaultValues: T
}

const defaultProductSearchWithoutCustomization = factoryParameters(
config,
defaultValues
)

const ConfigurableProductSearchContext = createContext(
defaultProductSearchWithoutCustomization
)

const SearchProvider: FC<Props> = ({
defaultValues: thisDefaultValues,
children,
}) => {
const value = useMemo(() => {
return factoryParameters(config, () => ({
...defaultValues(),
...thisDefaultValues,
}))
}, [thisDefaultValues])

return (
<ConfigurableProductSearchContext.Provider value={value}>
{children}
</ConfigurableProductSearchContext.Provider>
)
}

const useQuery = () => {
const { useQuery: thisUseQuery } = useContext(
ConfigurableProductSearchContext
)
return thisUseQuery()
}
import React, { useCallback, useState } from 'react'
import Geschichte from '../index'
import {
SearchProvider,
useQuery as useDefaultQuery,
} from '../examples/defaults'

afterEach(cleanup)

Expand All @@ -65,12 +17,12 @@ describe('<Geschichte /> dynamic defaults', () => {
const ComponentThatDisplaysValue = () => {
const {
values: { someParameter },
} = useQuery()
} = useDefaultQuery()
return <span role="content">{someParameter}</span>
}

const ComponentThatUsesQuery = () => {
const { pushState } = useQuery()
const { pushState } = useDefaultQuery()
return (
<>
<button
Expand Down
54 changes: 54 additions & 0 deletions src/examples/defaults.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { pm } from '../lib/utils'
import { serializers } from '../lib/serializers'
import { factoryParameters } from '../lib/store'
import React, { createContext, FC, useContext, useMemo } from 'react'

const config = {
someParameter: pm('wow', serializers.string),
}
const defaultValues = () => ({
someParameter: 'test',
})

interface Props<T = {}> {
readonly defaultValues: T
}

const defaultProductSearchWithoutCustomization = factoryParameters(
config,
defaultValues,
'some'
)

const ConfigurableProductSearchContext = createContext(
defaultProductSearchWithoutCustomization
)

export const SearchProvider: FC<Props> = ({
defaultValues: thisDefaultValues,
children,
}) => {
const value = useMemo(() => {
return factoryParameters(
config,
() => ({
...defaultValues(),
...thisDefaultValues,
}),
'some'
)
}, [thisDefaultValues])

return (
<ConfigurableProductSearchContext.Provider value={value}>
{children}
</ConfigurableProductSearchContext.Provider>
)
}

export const useQuery = () => {
const { useQuery: thisUseQuery } = useContext(
ConfigurableProductSearchContext
)
return thisUseQuery()
}
34 changes: 33 additions & 1 deletion src/examples/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
/* tslint:disable:no-expression-statement no-object-mutation */
import { createBrowserHistory } from 'history'
import React from 'react'
import React, { createContext, FC, useCallback, useMemo, useState } from 'react'
import Geschichte, { factoryParameters, pm, serializers } from '../index'
import { SearchProvider, useQuery as useDefaultableQuery } from './defaults'

const history = createBrowserHistory()

Expand Down Expand Up @@ -65,9 +66,40 @@ const DifferentApp = () => {
)
}

const ComponentThatDisplaysValue = () => {
const {
values: { someParameter },
initialValues,
} = useDefaultableQuery()
return (
<div>
Now: {someParameter}, {JSON.stringify(initialValues)}
</div>
)
}

const DefaultValueWrapper = () => {
const [values, setValues] = useState({ someParameter: 'current default' })

const setNewDefaults = useCallback(() => {
setValues({ someParameter: 'new default' })
}, [setValues])

return (
<SearchProvider defaultValues={values}>
<button title="resetDefaults" onClick={setNewDefaults}>
Update defaults
</button>
<ComponentThatDisplaysValue />
<ComponentThatDisplaysValue />
</SearchProvider>
)
}

export const App = () => (
<>
<Geschichte history={history}>
<DefaultValueWrapper />
<h3>A sample Appliations</h3>
<InnerApp />
<DifferentApp />
Expand Down
7 changes: 4 additions & 3 deletions src/lib/middleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export interface NamespaceValues<ValueState extends object> {
mappedConfig: MappedConfig
config: Config
query: object
unsubscribe: () => void
unsubscribe: () => boolean
}

export type PushStateFunction<T> = (
Expand All @@ -46,7 +46,7 @@ export interface InnerNamespace<T extends object> {
}

interface RegistryPayload<ValueState> {
unsubscribe: () => void
unsubscribe: () => boolean
values: ValueState
initialValues: ValueState
}
Expand Down Expand Up @@ -424,11 +424,12 @@ export const converter =
delete thisState[ns]
}
}, HistoryEventType.REGISTER)
return !get().namespaces[ns]
}
state.mappedConfig = mappedConfig
state.config = config
state.initialValues = initialValues
state.values = initialValues
state.values = values
state.query = query
},
HistoryEventType.REGISTER,
Expand Down
14 changes: 3 additions & 11 deletions src/lib/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -185,18 +185,8 @@ export const factoryParameters = <T extends object>(
}),
shallow
)

const initialRegisterState = useMemo(() => {
const namespaceData = useStore.getState().namespaces[ns] || {}
const initialValues = memCreateInitialValues(defaultInitialValues)
const { values, query } = namespaceData
if (values) {
return {
initialValues,
query,
values,
}
}
return memInitBlank(initialQueries(), initialValues)
}, [useStore, defaultInitialValues])

Expand All @@ -220,7 +210,9 @@ export const factoryParameters = <T extends object>(
)
if (
initialRegisterState.values !== values ||
initialRegisterState.initialValues !== initialValues
initialRegisterState.initialValues !== initialValues ||
currentState.initialValues !== initialValues ||
currentState.values !== values
) {
setCurrentState({ values, initialValues })
}
Expand Down
26 changes: 13 additions & 13 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -12043,13 +12043,13 @@ react-docgen@^5.0.0:
node-dir "^0.1.10"
strip-indent "^3.0.0"

react-dom@^18.0.0:
version "18.0.0"
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.0.0.tgz#26b88534f8f1dbb80853e1eabe752f24100d8023"
integrity sha512-XqX7uzmFo0pUceWFCt7Gff6IyIMzFUn7QMZrbrQfGxtaxXZIcGQzoNpRLE3fQLnS4XzLLPMZX2T9TRcSrasicw==
react-dom@^18.1.0:
version "18.1.0"
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.1.0.tgz#7f6dd84b706408adde05e1df575b3a024d7e8a2f"
integrity sha512-fU1Txz7Budmvamp7bshe4Zi32d0ll7ect+ccxNu9FlObT605GOEB8BfO4tmRJ39R5Zj831VCpvQ05QPBW5yb+w==
dependencies:
loose-envify "^1.1.0"
scheduler "^0.21.0"
scheduler "^0.22.0"

react-draggable@^4.4.3:
version "4.4.4"
Expand Down Expand Up @@ -12170,10 +12170,10 @@ react-textarea-autosize@^8.3.0:
use-composed-ref "^1.0.0"
use-latest "^1.0.0"

react@^18.0.0:
version "18.0.0"
resolved "https://registry.yarnpkg.com/react/-/react-18.0.0.tgz#b468736d1f4a5891f38585ba8e8fb29f91c3cb96"
integrity sha512-x+VL6wbT4JRVPm7EGxXhZ8w8LTROaxPXOqhlGyVSrv0sB1jkyFGgXxJ8LVoPRLvPR6/CIZGFmfzqUa2NYeMr2A==
react@^18.1.0:
version "18.1.0"
resolved "https://registry.yarnpkg.com/react/-/react-18.1.0.tgz#6f8620382decb17fdc5cc223a115e2adbf104890"
integrity sha512-4oL8ivCz5ZEPyclFQXaNksK3adutVS8l2xzZU0cqEFrE9Sb7fC0EFK5uEk74wIreL1DERyjvsU915j1pcT2uEQ==
dependencies:
loose-envify "^1.1.0"

Expand Down Expand Up @@ -12804,10 +12804,10 @@ saxes@^5.0.1:
dependencies:
xmlchars "^2.2.0"

scheduler@^0.21.0:
version "0.21.0"
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.21.0.tgz#6fd2532ff5a6d877b6edb12f00d8ab7e8f308820"
integrity sha512-1r87x5fz9MXqswA2ERLo0EbOAU74DpIUO090gIasYTqlVoJeMcl+Z1Rg7WHz+qtPujhS/hGIt9kxZOYBV3faRQ==
scheduler@^0.22.0:
version "0.22.0"
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.22.0.tgz#83a5d63594edf074add9a7198b1bae76c3db01b8"
integrity sha512-6QAm1BgQI88NPYymgGQLCZgvep4FyePDWFpXVK+zNSUgHwlqpJy8VEh8Et0KxTACS4VWwMousBElAZOH9nkkoQ==
dependencies:
loose-envify "^1.1.0"

Expand Down

0 comments on commit 040db01

Please sign in to comment.