},
- )
- return (
- <>
-
- count: {snap.count}, delayedCount: {use2(snap.delayedCount)}
-
-
- >
- )
- }
-
- const { getByText, findByText } = render(
-
-
-
-
- ,
- )
-
- await findByText('loading')
- await findByText('count: 0, delayedCount: 1')
-
- fireEvent.click(getByText('button'))
- await findByText('loading')
- await findByText('count: 1, delayedCount: 2')
-})
-
-it('nested emulation with derive', async () => {
- const computeDouble = vi.fn((x: number) => x * 2)
- const state = proxy({ text: '', math: { count: 0 } })
- derive(
- {
- doubled: (get) => computeDouble(get(state.math).count),
- },
- { proxy: state.math, sync: true },
- )
-
- const callback = vi.fn()
- subscribe(state, callback)
-
- expect(snapshot(state)).toMatchObject({
- text: '',
- math: { count: 0, doubled: 0 },
- })
- expect(computeDouble).toBeCalledTimes(1)
- expect(callback).toBeCalledTimes(0)
-
- state.math.count += 1
- await Promise.resolve()
- expect(snapshot(state)).toMatchObject({
- text: '',
- math: { count: 1, doubled: 2 },
- })
- expect(computeDouble).toBeCalledTimes(2)
- await Promise.resolve()
- expect(callback).toBeCalledTimes(1)
-
- state.text = 'a'
- await Promise.resolve()
- expect(snapshot(state)).toMatchObject({
- text: 'a',
- math: { count: 1, doubled: 2 },
- })
- expect(computeDouble).toBeCalledTimes(2)
- await Promise.resolve()
- expect(callback).toBeCalledTimes(2)
-})
-
-it('derive with array.pop', async () => {
- const state = proxy({
- arr: [{ n: 1 }, { n: 2 }, { n: 3 }],
- })
- derive(
- {
- nums: (get) => get(state.arr).map((item) => item.n),
- },
- { proxy: state },
- )
-
- expect(snapshot(state)).toMatchObject({
- arr: [{ n: 1 }, { n: 2 }, { n: 3 }],
- nums: [1, 2, 3],
- })
-
- state.arr.pop()
- await Promise.resolve()
- expect(snapshot(state)).toMatchObject({
- arr: [{ n: 1 }, { n: 2 }],
- nums: [1, 2],
- })
-})
-
-it('basic underive', async () => {
- const computeDouble = vi.fn((x: number) => x * 2)
- const state = proxy({ count: 0 })
- const derived = derive({
- doubled: (get) => computeDouble(get(state).count),
- })
-
- const callback = vi.fn()
- subscribe(derived, callback)
-
- expect(snapshot(derived)).toMatchObject({ doubled: 0 })
- expect(computeDouble).toBeCalledTimes(1)
- expect(callback).toBeCalledTimes(0)
-
- state.count += 1
- await Promise.resolve()
- expect(snapshot(derived)).toMatchObject({ doubled: 2 })
- expect(computeDouble).toBeCalledTimes(2)
- await Promise.resolve()
- expect(callback).toBeCalledTimes(1)
-
- underive(derived)
-
- state.count += 1
- await Promise.resolve()
- expect(snapshot(derived)).toMatchObject({ doubled: 2 })
- expect(computeDouble).toBeCalledTimes(2)
- await Promise.resolve()
- expect(callback).toBeCalledTimes(1)
-})
-
-describe('glitch free', () => {
- it('basic (#296)', async () => {
- const state = proxy({ value: 0 })
- const derived1 = derive({ value: (get) => get(state).value })
- const derived2 = derive({ value: (get) => get(derived1).value })
- const computeValue = vi.fn((get: DeriveGet) => {
- const v0 = get(state).value
- const v1 = get(derived1).value
- const v2 = get(derived2).value
- return `v0: ${v0}, v1: ${v1}, v2: ${v2}`
- })
- const derived3 = derive({ value: computeValue })
-
- const App = () => {
- const snap = useSnapshot(derived3)
- const commitsRef = useRef(1)
- useEffect(() => {
- commitsRef.current += 1
- })
- return (
- <>
- value: {snap.value} (commits: {commitsRef.current})
-
- >
- )
- }
-
- const { getByText, findByText } = render(
- <>
-
- >,
- )
-
- await findByText('value: v0: 0, v1: 0, v2: 0 (commits: 1)')
- expect(computeValue).toBeCalledTimes(1)
-
- fireEvent.click(getByText('button'))
- await findByText('value: v0: 1, v1: 1, v2: 1 (commits: 2)')
- expect(computeValue).toBeCalledTimes(2)
- })
-
- it('same value', async () => {
- const state = proxy({ value: 0 })
- const derived1 = derive({
- value: (get) => get(state).value * 0,
- })
- const derived2 = derive({
- value: (get) => get(derived1).value * 0,
- })
- const computeValue = vi.fn((get: DeriveGet) => {
- const v0 = get(state).value
- const v1 = get(derived1).value
- const v2 = get(derived2).value
- return v0 + (v1 - v2)
- })
- const derived3 = derive({
- value: (get) => computeValue(get),
- })
-
- const App = () => {
- const snap = useSnapshot(derived3)
- return (
-
- value: {snap.value}
-
-
- )
- }
-
- const { getByText, findByText } = render(
-
-
- ,
- )
-
- await findByText('value: 0')
- expect(computeValue).toBeCalledTimes(1)
-
- fireEvent.click(getByText('button'))
- await findByText('value: 1')
- expect(computeValue).toBeCalledTimes(2)
- })
-
- it('double chain', async () => {
- const state = proxy({ value: 0 })
- const derived1 = derive({
- value: (get) => get(state).value,
- })
- const derived2 = derive({
- value: (get) => get(derived1).value,
- })
- const derived3 = derive({
- value: (get) => get(derived2).value,
- })
- const computeValue = vi.fn((get: DeriveGet) => {
- const v0 = get(state).value
- const v1 = get(derived1).value
- const v2 = get(derived2).value
- const v3 = get(derived3).value
- return v0 + (v1 - v2) + v3 * 0
- })
- const derived4 = derive({
- value: (get) => computeValue(get),
- })
-
- const App = () => {
- const snap = useSnapshot(derived4)
- return (
-
- value: {snap.value}
-
-
- )
- }
-
- const { getByText, findByText } = render(
-
-
- ,
- )
-
- await findByText('value: 0')
- expect(computeValue).toBeCalledTimes(1)
-
- fireEvent.click(getByText('button'))
- await findByText('value: 1')
- expect(computeValue).toBeCalledTimes(2)
- })
-})
-
-describe('two derived properties', () => {
- type State = {
- a: number
- derived1?: unknown
- derived2?: unknown
- }
-
- it('two derived properties both returning primitive values (#349)', async () => {
- const state: State = proxy({ a: 1 })
- derive(
- {
- derived1: (get) => {
- get(state).a
- return 1
- },
- },
- { proxy: state },
- )
- derive(
- {
- derived2: (get) => {
- get(state).a
- return 1
- },
- },
- { proxy: state },
- )
- await Promise.resolve()
- expect(state.derived1).toBeDefined()
- expect(state.derived2).toBeDefined()
- })
-
- it('two derived properties both returning non primitive values, defined at the same time (#349)', async () => {
- const state: State = proxy({ a: 1 })
- derive(
- {
- derived1: (get) => {
- get(state).a
- return {}
- },
- derived2: (get) => {
- get(state).a
- return {}
- },
- },
- { proxy: state },
- )
- await Promise.resolve()
- expect(state.derived1).toBeDefined()
- expect(state.derived2).toBeDefined()
- })
-
- it('two derived properties both returning non primitive values (#349)', async () => {
- const state: State = proxy({ a: 1 })
- derive(
- {
- derived1: (get) => {
- get(state).a
- return {}
- },
- },
- { proxy: state },
- )
- derive(
- {
- derived2: (get) => {
- get(state).a
- return {}
- },
- },
- { proxy: state },
- )
- await Promise.resolve()
- expect(state.derived1).toBeDefined()
- expect(state.derived2).toBeDefined()
- })
-})
diff --git a/yarn.lock b/yarn.lock
index 425392e3..f4f5899a 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2322,11 +2322,6 @@ delayed-stream@~1.0.0:
resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==
-derive-valtio@0.1.0:
- version "0.1.0"
- resolved "https://registry.yarnpkg.com/derive-valtio/-/derive-valtio-0.1.0.tgz#4b9fb393dfefccfef15fcbbddd745dd22d5d63d7"
- integrity sha512-OCg2UsLbXK7GmmpzMXhYkdO64vhJ1ROUUGaTFyHjVwEdMEcTTRj7W1TxLbSBxdY8QLBPCcp66MTyaSy0RpO17A==
-
diff-sequences@^29.4.3:
version "29.6.3"
resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-29.6.3.tgz#4deaf894d11407c51efc8418012f9e70b84ea921"