Skip to content

Commit

Permalink
chore: merge next/v1.3.x branch (#117)
Browse files Browse the repository at this point in the history
@affects atoms, react
  • Loading branch information
bowheart authored Sep 17, 2024
1 parent b157917 commit b79f36a
Show file tree
Hide file tree
Showing 23 changed files with 407 additions and 241 deletions.
15 changes: 15 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "Debug Tests",
"type": "node",
"request": "launch",
"runtimeExecutable": "yarn",
"args": ["jest", "--runInBand"],
"console": "integratedTerminal",
"cwd": "${workspaceRoot}",
"internalConsoleOptions": "neverOpen"
},
]
}
20 changes: 20 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,23 @@
## v1.3.0-rc.2 (Jul 31, 2024)

### Fixes:

- `react`: only rerun `useAtomSelector` effect on cache id change (#110)

## v1.3.0-rc.1 (Jul 30, 2024)

### Fixes:

- `react`: restore `useAtomSelector` mounted state when swapping inline refs (#108)

## v1.3.0-rc.0 (Jul 30, 2024)

This version contains huge fixes for `useAtomSelector` that are only fully compatible with React 19 or with React 18 when not using StrictMode. It's recommended to wait for React 19 before upgrading to this version.

### Fixes:

- `atoms`, `react`: optimize `useAtomSelector` for React 19 (#106)

## v1.2.3 (Sep 7, 2024)

### Fixes:
Expand Down
35 changes: 35 additions & 0 deletions jest.setup.ts
Original file line number Diff line number Diff line change
@@ -1 +1,36 @@
import '@testing-library/jest-dom/extend-expect'

let callstacks: Record<string, string> = {}
let id = 0

afterEach(() => {
callstacks = {}
id = 0
})

const generateId = () => {
const stack =
(new Error().stack || '')
.split('\n')
.find(line => /\.test\.tsx:/.test(line)) || ''

return (callstacks[stack] ||= `:r${id++}:`)
}

jest.mock('react', () => ({
...jest.requireActual('react'),
useId: generateId,
}))

// React's `useId` gives new ids in the same callstack when a component tree is
// destroyed/unmounted. Call this to manually force ids to be recreated in tests
// to mimic React's behavior.
;(globalThis as any).clearUseIdEntry = (idNum: number) => {
const key = Object.keys(callstacks).find(
key => callstacks[key] === `:r${idNum}:`
)

if (key) {
delete callstacks[key]
}
}
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "zedux",
"version": "1.2.3",
"version": "1.3.0-rc.2",
"description": "A Molecular State Engine for React",
"type": "module",
"author": "Joshua Claunch (bowheart <[email protected]>)",
Expand Down
4 changes: 2 additions & 2 deletions packages/atoms/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@zedux/atoms",
"version": "1.2.3",
"version": "1.3.0-rc.2",
"description": "A Molecular State Engine for React",
"main": "./dist/cjs/index.js",
"module": "./dist/esm/index.js",
Expand All @@ -10,7 +10,7 @@
"url": "https://github.com/Omnistac/zedux/issues"
},
"dependencies": {
"@zedux/core": "^1.2.3"
"@zedux/core": "^1.3.0-rc.2"
},
"exports": {
".": {
Expand Down
40 changes: 14 additions & 26 deletions packages/atoms/src/classes/Selectors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,18 +48,6 @@ export class Selectors {
*/
public _refBaseKeys = new WeakMap<AtomSelectorOrConfig<any, any>, string>()

/**
* Used to work around React double-renders and double-effects.
*/
public _storage: Record<
string,
{
cache?: SelectorCache
ignorePhase?: number
timeoutId?: ReturnType<typeof requestIdleCallback | typeof setTimeout>
}
> = {}

constructor(private readonly ecosystem: Ecosystem) {}

public addDependent(
Expand Down Expand Up @@ -182,9 +170,8 @@ export class Selectors {
args as Args,
true
)
if (!id) return

return this._items[id]
return id && this._items[id]
}

/**
Expand Down Expand Up @@ -369,20 +356,19 @@ export class Selectors {
/**
* Should only be used internally
*/
public _swapRefs(
oldRef: AtomSelectorOrConfig<any, any[]>,
newRef: AtomSelectorOrConfig<any, any[]>,
public _swapRefs<T, Args extends any[]>(
oldCache: SelectorCache<T, Args>,
newRef: AtomSelectorOrConfig<T, Args>,
args: any[] = []
) {
const existingCache = this.find(oldRef, args)
const baseKey = this._refBaseKeys.get(oldRef)
const baseKey = this._refBaseKeys.get(oldCache.selectorRef)

if (!existingCache || !baseKey) return
if (!baseKey) return

this._refBaseKeys.set(newRef, baseKey)
this._refBaseKeys.delete(oldRef)
existingCache.selectorRef = newRef
this.runSelector(existingCache.id, args)
this._refBaseKeys.delete(oldCache.selectorRef)
oldCache.selectorRef = newRef
this.runSelector(oldCache.id, args, false, true)
}

/**
Expand All @@ -395,7 +381,6 @@ export class Selectors {
})

this._refBaseKeys = new WeakMap()
this._storage = {}
}

/**
Expand Down Expand Up @@ -429,7 +414,8 @@ export class Selectors {
private runSelector<T = any, Args extends any[] = []>(
id: string,
args: Args,
isInitializing?: boolean
isInitializing?: boolean,
skipNotifyingDependents?: boolean
) {
const { _evaluationStack, _graph, _mods, modBus } = this.ecosystem
_graph.bufferUpdates(id)
Expand All @@ -451,7 +437,9 @@ export class Selectors {
const result = selector(_evaluationStack.atomGetters, ...args)

if (!isInitializing && !resultsComparator(result, cache.result as T)) {
_graph.scheduleDependents(id, cache.nextReasons, result, cache.result)
if (!skipNotifyingDependents) {
_graph.scheduleDependents(id, cache.nextReasons, result, cache.result)
}

if (_mods.stateChanged) {
modBus.dispatch(
Expand Down
2 changes: 1 addition & 1 deletion packages/core/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@zedux/core",
"version": "1.2.3",
"version": "1.3.0-rc.2",
"description": "A high-level, declarative, composable form of Redux",
"main": "./dist/cjs/index.js",
"module": "./dist/esm/index.js",
Expand Down
6 changes: 3 additions & 3 deletions packages/immer/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@zedux/immer",
"version": "1.2.3",
"version": "1.3.0-rc.2",
"description": "Official Immer integration for Zedux's store and atomic APIs",
"main": "./dist/cjs/index.js",
"module": "./dist/esm/index.js",
Expand All @@ -10,7 +10,7 @@
"url": "https://github.com/Omnistac/zedux/issues"
},
"devDependencies": {
"@zedux/atoms": "^1.2.3",
"@zedux/atoms": "^1.3.0-rc.2",
"immer": "^9.0.21"
},
"exports": {
Expand Down Expand Up @@ -41,7 +41,7 @@
],
"license": "MIT",
"peerDependencies": {
"@zedux/atoms": "^1.2.3",
"@zedux/atoms": "^1.3.0-rc.2",
"immer": ">=9.0.19"
},
"repository": {
Expand Down
6 changes: 3 additions & 3 deletions packages/machines/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@zedux/machines",
"version": "1.2.3",
"version": "1.3.0-rc.2",
"description": "Simple native state machine implementation for Zedux atoms",
"main": "./dist/cjs/index.js",
"module": "./dist/esm/index.js",
Expand All @@ -10,7 +10,7 @@
"url": "https://github.com/Omnistac/zedux/issues"
},
"devDependencies": {
"@zedux/atoms": "^1.2.3"
"@zedux/atoms": "^1.3.0-rc.2"
},
"exports": {
".": {
Expand Down Expand Up @@ -41,7 +41,7 @@
],
"license": "MIT",
"peerDependencies": {
"@zedux/atoms": "^1.2.3"
"@zedux/atoms": "^1.3.0-rc.2"
},
"repository": {
"directory": "packages/machines",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {
InjectMachineStoreParams,
MachineState,
} from '@zedux/machines'
import { api, atom } from '@zedux/react'
import { api, atom } from '@zedux/atoms'
import { ecosystem } from '../../../react/test/utils/ecosystem'

const injectMachine = <
Expand Down
2 changes: 1 addition & 1 deletion packages/machines/test/snippets/api.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
ion,
useAtomSelector,
useAtomValue,
} from '@zedux/react'
} from '../../../react/src'
import { injectMachineStore } from '@zedux/machines'
import React, { Suspense, useState } from 'react'

Expand Down
15 changes: 8 additions & 7 deletions packages/react/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@zedux/react",
"version": "1.2.3",
"version": "1.3.0-rc.2",
"description": "A Molecular State Engine for React",
"main": "./dist/cjs/index.js",
"module": "./dist/esm/index.js",
Expand All @@ -10,14 +10,15 @@
"url": "https://github.com/Omnistac/zedux/issues"
},
"dependencies": {
"@zedux/atoms": "^1.2.3"
"@zedux/atoms": "^1.3.0-rc.2"
},
"devDependencies": {
"@testing-library/dom": "^10.4.0",
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^14.0.0",
"@types/react-dom": "^18.0.11",
"react": "^18.2.0",
"react-dom": "^18.2.0"
"@testing-library/react": "^16.0.1",
"@types/react-dom": "^18.3.0",
"react": "^19.0.0-rc-ee1a403a-20240916",
"react-dom": "^19.0.0-rc-ee1a403a-20240916"
},
"exports": {
".": {
Expand Down Expand Up @@ -55,7 +56,7 @@
],
"license": "MIT",
"peerDependencies": {
"react": ">=18.0.0"
"react": ">=19.0.0"
},
"repository": {
"directory": "packages/react",
Expand Down
6 changes: 5 additions & 1 deletion packages/react/src/hooks/useAtomInstance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,12 @@ export const useAtomInstance: {
}

return () => {
// no need to set the "ref"'s `.mounted` property to false here
// remove the edge immediately - no need for a delay here. When StrictMode
// double-invokes (invokes, then cleans up, then re-invokes) this effect,
// it's expected that any `ttl: 0` atoms get destroyed and recreated -
// that's part of what StrictMode is ensuring
ecosystem._graph.removeEdge(dependentKey, instance.id)
// no need to set `render.mounted` to false here
}
}, [instance.id])

Expand Down
Loading

0 comments on commit b79f36a

Please sign in to comment.