@statekit/react
v0.5.0-alpha
Published
Check out `@statekit/core`!
Downloads
1
Readme
statekit PoC WIP
Check out @statekit/core
!
There it explains the latest version but here is a summary:
const config = createDfaConfig({
states: ["idle", "running", "paused"],
data: initialData,
events: {
noop: () => {},
data: ({ draft }) => {
//console.log(draft)
draft
},
payload: ({ draft }, p: Partial<Data>) => {
Object.assign(draft, p)
},
meta: (meta) => {
meta.draft.foo = meta.state.toString()
},
return: ({ isStateOneOf, S }) => {
if (isStateOneOf([S.idle, S.paused])) return
},
cases: ({ cases, S, draft }) =>
cases({
[S.idle]: () => S.running,
[S.paused]: () => {
draft.count = 123
},
}),
async: async ({ draft, S }) => {
draft.foo = "loading"
draft.foo = await anAsyncFn("success")
return S.running
},
},
helpers: {
isCountZero: ({ data }) => data.count === 0,
isCountEqualTo: ({ data }, to: number) => data.count === to,
isDataSameAs: ({ data }, payload: { count: number; foo: string }) =>
data.count === payload.count && data.foo == payload.foo,
},
transitionRules: {
only: {
paused: ["running"],
},
deny: {
running: ["paused"],
},
},
})
//...
it("should emit events", () => {
const m = createDfa(config)
const { event } = m
event.noop()
expect(m.data).toEqual(initialData)
event.data()
expect(m.data).toEqual(initialData)
event.payload({ count: 1 })
expect(m.data).toEqual({ ...initialData, count: 1 })
event.meta()
expect(m.data.foo).toEqual(m.state.toString())
})
And in React tests:
import * as React from "react"
import { StatekitProvider } from "../feat/statekit"
import { createMachineContext } from "../feat/machine/createMachineContext"
import { machineConfigFactory } from "./mock-factories/machineConfig"
import { createMachine } from "@statekit/core"
import { act, render, screen, fireEvent, cleanup } from "@testing-library/react"
const firstRootSiblingCfg = machineConfigFactory()
const secondRootSiblingCfg = machineConfigFactory({
count: -100,
foo: "second sibling",
})
const firstRootSiblingMachine = createMachine(firstRootSiblingCfg)
const secondRootSiblingMachine = createMachine(secondRootSiblingCfg)
const [FirstRootSiblingMachineProvider, useFirstRootSiblingMachine] =
createMachineContext(firstRootSiblingMachine)
const [SecondRootSiblingMachineProvider, useSecondRootSiblingMachine] =
createMachineContext(secondRootSiblingMachine)
const dataTestId = {
FirstRootSibling: "first-root-sibling",
SecondRootSibling: "second-root-sibling",
FirstRootSiblingFirstChild: "first-root-sibling-first-child",
FirstRootSiblingSecondChild: "first-root-sibling-second-child",
} as const
const Root = () => (
<StatekitProvider>
<FirstRootSibling>
<FirstRootSiblingFirstChild />
<FirstRootSiblingSecondChild />
</FirstRootSibling>
<SecondRootSibling />
</StatekitProvider>
)
const FirstRootSibling = ({ children }: { children?: React.ReactNode }) => {
const m = useFirstRootSiblingMachine()
return (
<FirstRootSiblingMachineProvider>
<span data-testid={dataTestId.FirstRootSibling}>{m.data.count}</span>
{children}
</FirstRootSiblingMachineProvider>
)
}
const SecondRootSibling = ({ children }: { children?: React.ReactNode }) => {
const m = useSecondRootSiblingMachine()
return (
<SecondRootSiblingMachineProvider>
<span data-testid={dataTestId.SecondRootSibling}>{m.data.count}</span>
{children}
</SecondRootSiblingMachineProvider>
)
}
const FirstRootSiblingFirstChild = () => {
const m = useFirstRootSiblingMachine()
return (
<span data-testid={dataTestId.FirstRootSiblingFirstChild}>{m.data.count}</span>
)
}
const FirstRootSiblingSecondChild = () => {
const m = useFirstRootSiblingMachine()
return (
<>
<span data-testid={dataTestId.FirstRootSiblingSecondChild}>
{m.data.count}
</span>
<button onClick={() => m.event.mutate({ count: 123 })}>
FirstRootSiblingSecondChild button
</button>
</>
)
}
const setup = () => {
const view = render(<Root />)
return { view }
}
afterEach(() => cleanup)
describe("Machine", () => {
it("SecondRootSibling initial data", () => {
setup()
const el = screen.getByTestId(dataTestId.SecondRootSibling)
expect(el.textContent).toBe(secondRootSiblingCfg.data.count.toString())
})
it("FirstRootSiblingFirstChild initial data from First machine", () => {
setup()
const el = screen.getByTestId(dataTestId.FirstRootSiblingFirstChild)
expect(el.textContent).toBe(firstRootSiblingCfg.data.count.toString())
})
it("events trigger re-render", () => {
setup()
const buttonEl = screen.getByText("FirstRootSiblingSecondChild button")
act(() => fireEvent.click(buttonEl))
const countEl = screen.getByTestId(dataTestId.FirstRootSiblingSecondChild)
expect(countEl.textContent).toBe("123")
})
it("events can be received by a sibling", () => {
setup()
const buttonEl = screen.getByText("FirstRootSiblingSecondChild button")
act(() => fireEvent.click(buttonEl))
const siblingCountEl = screen.getByTestId(
dataTestId.FirstRootSiblingFirstChild
)
expect(siblingCountEl.textContent).toBe("123")
})
})