pmndrs / koota

🌎 Performant real-time state management for React and TypeScript
130 stars 5 forks source link

Move `createActions` to core #5

Closed krispya closed 2 weeks ago

krispya commented 1 month ago

Right now createActions lives in the React package and gets used as a hook.

import { createActions } from 'koota/react';

const useMyActions = createActions((world) => ({
    spawnShip: (position) => world.spawn(Position(position), Velocity),
    destroyAllShips: (world) => {
        world.query(Position, Velocity).forEach((entity) => {
            entity.destroy();
        });
    },
}));

function Component() {
    const { spawnShip, destroyAllShips } = useMyActions();
}

And then can be used in vanilla with an additional API call that binds world to the actions manually.

    const { spawnShip, destroyAllShips } = useMyActions.get(world)

This was inspired by the Zustand API but it turns out actions are really useful for vanilla making me think it is better to flip this around and make it a core export that always takes a world to bind.

import { createActions } from 'koota';

const useMyActions = createActions((world) => ({
    spawnShip: (position) => world.spawn(Position(position), Velocity),
    destroyAllShips: (world) => {
        world.query(Position, Velocity).forEach((entity) => {
            entity.destroy();
        });
    },
}));

function Component() {
    const world = useWorld()
    // Bind world manually. Can choose the world instead of getting it from context.
    const { spawnShip, destroyAllShips } = useMyActions(world);
}

// This is the exact same API for vanilla.
const { spawnShip, destroyAllShips } = useMyActions(world);
krispya commented 2 weeks ago

Following Zustand's lead, I am looking to do this instead:

import { actions } from 'koota'
import { useActions } from 'koota/react'

const actions = createActions((world) => {})

// Vanilla use
const { spawnPlayer } = actions(world)

// React use
const { spawnPlayer } = useActions(actions)