@arancini/react
React glue for the arancini Entity Component System.
Installation
> npm install @arancini/react
Creating the React glue
To get started, use createReactAPI
to get glue components and hooks scoped to a given arancini world. Because the react glue is scoped, libraries can use @arancini/react without worrying about context conflicts.
import { World } from '@arancini/core'
import { createReactAPI } from '@arancini/react'
type EntityType = {
health?: number
position?: [number, number]
}
const world = new World<EntityType>()
const { Entity, Entities, Component, useQuery } = createReactAPI(world)
Entities and Components
<Entity />
can be used to declaratively create entities with components.
const Example = () => <Entity health={100} position={[0, 0]} />
You can also pass an existing entity to <Entity />
.
const entity = world.create({ position: [0, 0] })
const Example = () => <Entity entity={entity} health={100} />
<Component />
can be used to add components to an entity.
const Example = () => (
<Entity>
<Component name="health" value={100} />
</Entity>
)
Capturing React Component refs
If a child is passed to Component
, it will be captured and used as the value of the component. This is useful for keeping your logic decoupled from React.
const RefCaptureExample = () => (
<Entity>
<Component name="object3D">
<mesh>
<boxGeometry args={[1, 1, 1]} />
<meshNormalMaterial />
</mesh>
</Component>
</Entity>
)
Rendering multiple entities
@arancini/react
also provides an <Entities />
component that can be used to render a collection of entities or add components to existing entities. <Entities />
also supports render props.
const Simple = () => <Entities in={[entity1, entity2]}>{/* ... */}</Entities>
const AddComponentToEntities = () => (
<Entities in={[entity1, entity2]}>
<Component name="position" value={[0, 0]} />
</Entities>
)
const RenderProps = () => (
<Entities in={[entity1, entity2]}>
{(entity) => {
// ...
}}
</Entities>
)
Entities
can also be passed a query.
const withExampleTag = world.query((e) => e.with('exampleTag'))
const SimpleExample = () => (
<Entities in={withExampleTag}>
<mesh>
<boxGeometry args={[1, 1, 1]} />
<meshNormalMaterial />
</mesh>
</Entities>
)
Queries
useQuery
The useQuery
hook subscribes a component to a query, re-rendering the component when entities are added to or removed from the query.
const withHealth = world.query((e) => e.with('health'))
const Example = () => {
const entitiesWithHealth = useQuery(withHealth)
}