Skip to content

Commit

Permalink
Merge branch 'main' into feat/unstable_createStore
Browse files Browse the repository at this point in the history
  • Loading branch information
dai-shi committed Jan 18, 2022
2 parents 3c203a0 + 3a46e3e commit 07a0285
Show file tree
Hide file tree
Showing 6 changed files with 323 additions and 263 deletions.
8 changes: 2 additions & 6 deletions .github/workflows/test-multiple-versions.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ jobs:
- 16.9.0
- 17.0.0
- 18.0.0-rc.0
- 0.0.0-experimental-fe905f152-20220107
- 0.0.0-experimental-51947a14b-20220113
mode: [NORMAL, PROVIDER_LESS, VERSIONED_WRITE]
testing: [default, alpha]
exclude:
Expand All @@ -49,7 +49,7 @@ jobs:
- { react: 16.9.0, testing: alpha }
- { react: 17.0.0, testing: alpha }
- { react: 18.0.0-rc.0, testing: default } # suspense doesn't work?
- { react: 0.0.0-experimental-fe905f152-20220107, testing: default } # suspense doesn't work?
- { react: 0.0.0-experimental-51947a14b-20220113, testing: default } # suspense doesn't work?
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
Expand All @@ -61,10 +61,6 @@ jobs:
- name: Install alpha testing-library
if: ${{ matrix.testing == 'alpha' }}
run: yarn add -D @testing-library/react@alpha
- name: Patch for React 16.8
if: ${{ startsWith(matrix.react, '16.8.') }}
run: |
sed -i~ 's/it(.async atom double chain without setTimeout (#751).,/it.skip("async atom double chain without setTimeout (#751)",/' tests/async.test.tsx
- name: Patch for React 16
if: ${{ startsWith(matrix.react, '16.') }}
run: |
Expand Down
26 changes: 13 additions & 13 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "jotai",
"private": true,
"version": "1.5.2",
"version": "1.5.3",
"description": "👻 Next gen state management that will spook you",
"main": "./index.js",
"types": "./index.d.ts",
Expand Down Expand Up @@ -208,30 +208,30 @@
"@rollup/plugin-babel": "^5.3.0",
"@rollup/plugin-node-resolve": "^13.1.3",
"@rollup/plugin-typescript": "^8.3.0",
"@swc/core": "^1.2.127",
"@swc/jest": "^0.2.15",
"@swc/core": "^1.2.130",
"@swc/jest": "^0.2.17",
"@testing-library/react": "^12.1.2",
"@types/jest": "^27.4.0",
"@types/react": "^17.0.38",
"@types/react-dom": "^17.0.11",
"@typescript-eslint/eslint-plugin": "^5.9.1",
"@typescript-eslint/parser": "^5.9.1",
"@typescript-eslint/eslint-plugin": "^5.10.0",
"@typescript-eslint/parser": "^5.10.0",
"@urql/core": "^2.3.6",
"benny": "^3.7.1",
"concurrently": "^7.0.0",
"downlevel-dts": "^0.7.0",
"downlevel-dts": "^0.8.0",
"esbuild": "^0.14.11",
"eslint": "^8.6.0",
"eslint": "^8.7.0",
"eslint-config-prettier": "^8.3.0",
"eslint-import-resolver-alias": "^1.1.2",
"eslint-plugin-import": "^2.25.4",
"eslint-plugin-jest": "^25.3.4",
"eslint-plugin-jest": "^25.7.0",
"eslint-plugin-prettier": "^4.0.0",
"eslint-plugin-react": "^7.28.0",
"eslint-plugin-react-hooks": "^4.3.0",
"graphql": "^16.2.0",
"husky": "^7.0.4",
"immer": "^9.0.7",
"immer": "^9.0.12",
"jest": "^27.4.7",
"json": "^11.0.0",
"lint-staged": "^12.1.7",
Expand All @@ -240,17 +240,17 @@
"prettier": "^2.5.1",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-query": "^3.34.7",
"react-query": "^3.34.8",
"redux": "^4.1.2",
"rollup": "^2.63.0",
"rollup": "^2.64.0",
"rollup-plugin-esbuild": "^4.8.2",
"rxjs": "^7.5.1",
"rxjs": "^7.5.2",
"shx": "^0.3.4",
"ts-expect": "^1.3.0",
"ts-node": "^10.4.0",
"tslib": "^2.3.1",
"typescript": "^4.5.4",
"valtio": "^1.2.7",
"valtio": "^1.2.9",
"wonka": "^4.0.15",
"xstate": "^4.27.0",
"zustand": "^3.6.9"
Expand Down
16 changes: 15 additions & 1 deletion src/core/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,17 @@ export const createStore = (
if (nextAtomState.d.has(atom)) {
nextAtomState.d = new Map(nextAtomState.d).set(atom, nextAtomState.r)
}
} else if (
nextAtomState.d !== atomState.d &&
(nextAtomState.d.size !== atomState.d.size ||
!Array.from(nextAtomState.d.keys()).every((a) => atomState.d.has(a)))
) {
// value is not changed, but dependencies are changed
// we should schdule a flush in async
// FIXME any better way? https://github.com/pmndrs/jotai/issues/947
Promise.resolve().then(() => {
flushPending(version)
})
}
setAtomState(version, atom, nextAtomState)
return nextAtomState
Expand Down Expand Up @@ -793,7 +804,10 @@ export const createStore = (
const mounted = mountedMap.get(a)
if (mounted) {
mounted.t.add(atom) // add to dependents
} else {
} else if (mountedMap.has(atom)) {
// we mount dependencies only when atom is already mounted
// Note: we should revisit this when you find other issues
// https://github.com/pmndrs/jotai/issues/942
mountAtom(a, atom)
}
})
Expand Down
2 changes: 1 addition & 1 deletion src/devtools/useAtomsDevtools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ export function useAtomsDevtools(name: string, scope?: Scope) {
const { s: store, w: versionedWrite } = useContext(ScopeContext)

if (!store[DEV_SUBSCRIBE_STATE]) {
throw new Error('useAtomsSnapshot can only be used in dev mode.')
throw new Error('useAtomsDevtools can only be used in dev mode.')
}

const [atomsSnapshot, setAtomsSnapshot] = useState<AtomsSnapshot>(() => [
Expand Down
63 changes: 63 additions & 0 deletions tests/basic.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,40 @@ it('only re-renders if value has changed', async () => {
})
})

it('re-renders a time delayed derived atom with the same initial value (#947)', async () => {
const aAtom = atom(false)
aAtom.onMount = (set) => {
setTimeout(() => {
set(true)
})
}

const bAtom = atom(1)
bAtom.onMount = (set) => {
set(2)
}

const cAtom = atom((get) => {
if (get(aAtom)) {
return get(bAtom)
}
return 1
})

const App = () => {
const [value] = useAtom(cAtom)
return <>{value}</>
}

const { findByText } = render(
<Provider>
<App />
</Provider>
)

await findByText('2')
})

it('works with async get', async () => {
const countAtom = atom(0)
const asyncCountAtom = atom(async (get) => {
Expand Down Expand Up @@ -953,3 +987,32 @@ it('chained derive atom with onMount and useEffect (#897)', async () => {

await findByText('count: 1')
})

it('onMount is not called when atom value is accessed from writeGetter in derived atom (#942)', async () => {
const onUnmount = jest.fn()
const onMount = jest.fn(() => {
return onUnmount
})

const aAtom = atom(false)
aAtom.onMount = onMount

const bAtom = atom(null, (get) => {
get(aAtom)
})

const App = () => {
const [, action] = useAtom(bAtom)
useEffect(() => action(), [action])
return null
}

render(
<Provider>
<App />
</Provider>
)

expect(onMount).not.toBeCalled()
expect(onUnmount).not.toBeCalled()
})
Loading

0 comments on commit 07a0285

Please sign in to comment.