### Install solid-events
Source: https://github.com/devagrawal09/solid-events/blob/master/README.md
Provides instructions for installing the solid-events package using common package managers like npm, pnpm, and bun.
```bash
npm install solid-events
or
pnpm install solid-events
or
bun install solid-events
```
--------------------------------
### Imperative Drag and Drop Logic
Source: https://github.com/devagrawal09/solid-events/blob/master/README.md
Presents an example of handling drag-and-drop events with imperative logic. This includes conditional side effects and state mutations directly within event handlers, which can be hard to follow.
```ts
const [acceptDrop, setAcceptDrop] = createSignal<"top" | "bottom" | false>(
false
);
onDragOver={(e) => {
// check if a valid note is dragged over
if (!e.dataTransfer?.types.includes(DragTypes.Note)) {
// mutate state
setAcceptDrop(false);
return;
}
// calculate and mutate state based on position
const isTop = ...calculation;
setAcceptDrop(isTop ? "top" : "bottom");
}}
onDrop={(e) => {
// check if the dropped element is a valid note
if (e.dataTransfer?.types.includes(DragTypes.Note)) {
const noteId = e.dataTransfer?.getData(DragTypes.Note)
action: if (noteId && noteId !== props.note.id) {
// note is valid, run side effect
if (acceptDrop() === "top") {
if (props.previous && props.previous?.id === noteId) {
break action;
}
moveNoteAction(...);
}
if (acceptDrop() === "bottom") {
if (props.previous && props.next?.id === noteId) {
break action;
}
moveNoteAction(...);
}
}
}
// mutate state
setAcceptDrop(false);
}}
```
--------------------------------
### Create and Emit Events with createEvent
Source: https://github.com/devagrawal09/solid-events/blob/master/README.md
Demonstrates the fundamental usage of `createEvent` to generate an event handler and an emitter. It covers subscribing to events and emitting data payloads.
```ts
const [onEvent, emitEvent] = createEvent()
onEvent(payload => console.log(`Event emitted:`, payload))
...
emitEvent(`Hello World!`)
// logs "Event emitted: Hello World!"
```
--------------------------------
### Comparison of Reactive Primitives: RxJS vs. SolidJS
Source: https://github.com/devagrawal09/solid-events/blob/master/README.md
Discusses the fundamental differences between RxJS observables (push-based) and SolidJS signals (pull-based) in the context of functional reactive programming. It touches upon the historical evolution of FRP primitives.
```APIDOC
Reactive Primitive Comparison:
RxJS Observables:
- Paradigm: Push-based.
- Characteristics: Handles event composition, reactive state, lifecycles, higher-order streaming.
- Usage: Requires knowledge of operators and pipe syntax.
- Complexity: Can be complex due to the versatility of operators.
SolidJS Signals:
- Paradigm: Pull-based.
- Characteristics: Designed for specific roles (state, side effects, caching, lifecycles).
- Usage: Integrates seamlessly with Solid's declarative component model.
- Simplicity: Built using multiple, focused reactive primitives.
createEvent (SolidJS):
- Role: Reintroduces a push-based primitive into SolidJS.
- Goal: To complement signals and bring Solid closer to classic FRP semantics.
- Design: Lean and easy to learn, focusing solely on event composition.
```
--------------------------------
### Conceptual Overview of createEvent in SolidJS
Source: https://github.com/devagrawal09/solid-events/blob/master/README.md
Explains the purpose of `createEvent` in SolidJS, highlighting its role in event composition and its difference from RxJS observables. It positions `createEvent` as a complementary primitive to Solid's signals, effects, and memos.
```APIDOC
createEvent:
Purpose: Fills the void in SolidJS's reactive primitives for event composition.
Approach: Introduces a push-based primitive to complement Solid's pull-based signals.
Comparison to RxJS: Simpler, less powerful than RxJS observables, avoids complex operator chains.
Benefits: Easier to learn and integrate into Solid's existing system.
Limitations: Does not handle state management or higher-order streaming directly, relying on Solid's primitives for those tasks.
Context: Mentioned in conjunction with 'use socket' and server signals for full-stack reactivity.
```
--------------------------------
### Fine-Grained Mutations: Subject Store for State Updates
Source: https://github.com/devagrawal09/solid-events/blob/master/README.md
Simplifies fine-grained optimistic mutations by using a `createSubjectStore` to colocate and manage various state update events (notes, columns) in a single run.
```ts
const boardStore = createSubjectStore(
() => boardData(),
onCreateNote(([note]) => (board) => {
const index = board.notes.findIndex((n) => n.id === note.id);
if (index === -1) board.notes.push(note);
}),
onMoveNote(([noteId, columnId, order]) => (board) => {
const index = board.notes.findIndex((n) => n.id === noteId);
if (index !== -1) {
board.notes[index].column = columnId;
board.notes[index].order = order;
}
}),
onEditNote(...),
onDeleteNote(...),
onCreateColumn(...),
onRenameColumn(...),
onMoveColumn(...),
onDeleteColumn(...)
);
```
--------------------------------
### Create mutable state store with createSubjectStore
Source: https://github.com/devagrawal09/solid-events/blob/master/README.md
createSubjectStore provides a mutable store for state management, leveraging `produce` for direct state mutation within event handlers. It can be initialized with a signal and supports resetting and reconciliation.
```ts
const boardStore = createSubjectStore(
() => boardData(),
onCreateNote((createdNote) => (board) => {
const index = board.notes.findIndex((n) => n.id === note.id);
if (index === -1) board.notes.push(note);
}),
onDeleteNote(([id]) => (board) => {
const index = board.notes.findIndex((n) => n.id === id);
if (index !== -1) board.notes.splice(index, 1);
})
...
)
```
--------------------------------
### Imperative State Update with createSignal in SolidJS
Source: https://github.com/devagrawal09/solid-events/blob/master/README.md
Demonstrates a typical SolidJS component using `createSignal` for managing state imperatively. This approach allows direct mutation via setters, but tracking all mutations can become complex in larger applications.
```tsx
function Component() {
const [count, setCount] = createSignal(0)
const doubleCount = () => count() * 2
return
Count: {count()}
double Count: {doubleCount()}
}
```
--------------------------------
### Combine multiple events with createTopic
Source: https://github.com/devagrawal09/solid-events/blob/master/README.md
createTopic merges multiple event handlers into a single event stream. This simplifies handling multiple distinct events by providing a unified listener for all combined events.
```ts
const [onIncrement, emitIncrement] = createEvent()
const [onDecrement, emitDecrement] = createEvent()
const onMessage = createTopic(
onIncrement(() => `Increment by ${delta}`),
onDecrement(() => `Decrement by ${delta}`)
);
onMessage(message => console.log(`Message emitted:`, message))
...
emitIncrement(2)
// logs "Message emitted: Increment by 2"
emitDecrement(1)
// logs "Message emitted: Decrement by 1"
```
--------------------------------
### Transform Event Data with createEvent
Source: https://github.com/devagrawal09/solid-events/blob/master/README.md
Illustrates chaining transformations on event data by utilizing the return value of the event callback. This enables sequential processing of event payloads.
```ts
const [onIncrement, emitIncrement] = createEvent()
const onMessage = onIncrement((delta) => `Increment by ${delta}`)
onMessage(message => console.log(`Message emitted:`, message))
...
emitIncrement(2)
// logs "Message emitted: Increment by 2"
```
--------------------------------
### Event-Driven State Update with createEvent and createSubject in SolidJS
Source: https://github.com/devagrawal09/solid-events/blob/master/README.md
Illustrates an event-driven approach using `createEvent` and `createSubject` to derive state. All state changes are tied to specific events, making mutations explicit and easier to trace at declaration time.
```tsx
function Component() {
const [onIncrement, emitIncrement] = createEvent()
const count = createSubject(
0,
onIncrement(() => c => c + 1)
)
const doubleCount = () => count() * 2
return
Count: {count()}
double Count: {doubleCount()}
}
```
--------------------------------
### Optimistic Board Deletion with Async Subject
Source: https://github.com/devagrawal09/solid-events/blob/master/README.md
Achieves optimistic board deletion using an async subject and event handlers, simplifying state management compared to submission-based filtering.
```ts
const [onDeleteBoard, emitDeleteBoard] = createEvent();
onDeleteBoard(useAction(deleteBoard));
const boards = createAsyncSubject(
() => getBoards(),
onDeleteBoard(
(boardId) => (boards) => boards.filter((board) => board.id !== boardId)
)
);
```
--------------------------------
### Handle Async Events with createEvent
Source: https://github.com/devagrawal09/solid-events/blob/master/README.md
Explains how `createEvent` automatically handles promises returned from event callbacks. The event emission waits for the promise to resolve, effectively flattening asynchronous operations.
```ts
async function createBoard(boardData) {
"use server"
const boardId = await db.boards.create(boardData)
return boardId
}
const [onCreateBoard, emitCreateBoard] = createEvent()
const onBoardCreated = onCreateBoard(boardData => createBoard(boardData))
onBoardCreated(boardId => navigate(`/board/${boardId}`))
// If createBoard returns a promise, onBoardCreated will wait for it to resolve before navigating.
```
--------------------------------
### Manage Event Subscription Lifecycles in Components
Source: https://github.com/devagrawal09/solid-events/blob/master/README.md
Shows how event subscriptions created with `createEvent` are automatically managed and cleaned up when used within SolidJS components, preventing memory leaks.
```tsx
function Counter() {
const [onIncrement, emitIncrement] = createEvent()
const onMessage = onIncrement((delta) => `Increment by ${delta}`)
onMessage(message => console.log(`Message emitted:`, message))
return
....
}
// Calling onIncrement and onMessage registers stateful subscriptions tied to the component's lifecycle.
```
--------------------------------
### Optimistic Board Deletion with Submissions
Source: https://github.com/devagrawal09/solid-events/blob/master/README.md
Implements optimistic deletion of boards by filtering out deleted boards based on inflight submissions. Relies on `useSubmissions` and `createAsync`.
```ts
const serverBoards = createAsync(() => getBoards());
const deleteBoardSubmissions = useSubmissions(deleteBoard);
const boards = () => {
if (deleteBoardSubmissions.pending) {
const deletedBoards: number[] = [];
for (const sub of deleteBoardSubmissions) {
deletedBoards.push(sub.input[0]);
}
return serverBoards()?.filter(
(board) => !deletedBoards.includes(board.id)
);
}
return serverBoards();
};
```
--------------------------------
### Create and manage state with createSubject
Source: https://github.com/devagrawal09/solid-events/blob/master/README.md
createSubject creates a reactive signal that can be updated by event handlers. It can be initialized with a static value or a signal, and event handlers can return new values or updater functions. It supports resetting based on a source signal.
```ts
const [onIncrement, emitIncrement] = createEvent()
const [onReset, emitReset] = createEvent()
const onMessage = onIncrement((delta) => `Increment by ${delta}`)
onMessage(message => console.log(`Message emitted:`, message))
const count = createSubject(
0,
onIncrement(delta => currentCount => currentCount + delta),
onReset(() => 0)
)
createEffect(() => console.log(`count`, count()))
emitIncrement(2)
// logs "Message emitted: Increment by 2"
// logs "count 2"
emitReset()
// logs "count 0"
```
```tsx
function Counter(props) {
const [onIncrement, emitIncrement] = createEvent()
const [onReset, emitReset] = createEvent()
const count = createSubject(
() => props.count,
onIncrement(delta => currentCount => currentCount + delta),
onReset(() => 0)
)
return
...
}
```
--------------------------------
### Fine-Grained Mutations: Applying Mutations with Effects
Source: https://github.com/devagrawal09/solid-events/blob/master/README.md
Applies mutations to notes and columns using `createEffect` and `untrack`, updating the store with `reconcile` and `batch`. Handles state updates based on timestamps.
```ts
createEffect(() => {
const mutations = untrack(() => getMutations());
const { notes, columns } = props.board;
applyMutations(mutations, notes, columns);
batch(() => {
setBoardStore("notes", reconcile(notes));
setBoardStore("columns", reconcile(columns));
});
});
createEffect(() => {
const mutations = getMutations();
const prevTimestamp = untrack(() => boardStore.timestamp);
const latestMutations = mutations.filter(
(m) => m.timestamp > prevTimestamp
);
setBoardStore(
produce((b) => {
applyMutations(latestMutations, b.notes, b.columns);
b.timestamp = Date.now();
})
);
});
```
--------------------------------
### Halt Event Propagation with createEvent
Source: https://github.com/devagrawal09/solid-events/blob/master/README.md
Demonstrates how to stop event propagation at any point within the event handler chain using the `halt()` function. This prevents subsequent handlers from being executed.
```ts
const [onIncrement, emitIncrement] = createEvent()
const onValidIncrement = onIncrement(delta => delta < 1 ? halt() : delta)
const onMessage = onValidIncrement((delta) => `Increment by ${delta}`)
onMessage(message => console.log(`Message emitted:`, message))
...
emitIncrement(2)
// logs "Message emitted: Increment by 2"
...
emitIncrement(0)
// Doesn't log anything
```
--------------------------------
### Event Composition for Drag and Drop Logic
Source: https://github.com/devagrawal09/solid-events/blob/master/README.md
Refactors the drag-and-drop logic using event composition. This approach separates concerns, making decisions explicit events and moving side effects to the end of the flow for better readability and maintainability.
```ts
const onDropNote = onDrop((e) => {
// check if the dropped element is a valid note
if (!e.dataTransfer?.types.includes(DragTypes.Note)) halt();
const noteId = e.dataTransfer?.getData(DragTypes.Note);
if (!noteId || noteId === props.note.id) halt();
return noteId;
});
onDropNote((noteId) => {
// when a valid note is dropped, run side effect
if (acceptDrop() === "top" && props.previous?.id !== noteId) {
return moveNoteAction(...);
}
if (acceptDrop() === "bottom" && props.next?.id !== noteId) {
return moveNoteAction(...);
}
});
// check if a valid note is dragged over
const [onDragOverValidEl, onDragOverInvalidEl] = createPartition(
onDragOver,
(e) => !!e.dataTransfer?.types.includes(DragTypes.Note)
);
// derive highlight state based on element and position
const acceptDrop = createSubject<"top" | "bottom" | false>(
false,
onDrop(() => false),
onDragOverInvalidEl(() => false),
onDragOverValidEl((e) => {
const isTop = ...calculation
return isTop ? "top" : "bottom";
})
);
```
--------------------------------
### Conditionally split events with createPartition
Source: https://github.com/devagrawal09/solid-events/blob/master/README.md
createPartition splits a single event into two based on a condition, offering a cleaner alternative to `halt()`. It creates two new event handlers: one for events that meet the condition and one for those that don't.
```ts
const [onIncrement, emitIncrement] = createEvent()
const [onValidIncrement, onInvalidIncrement] = createPartition(
onIncrement,
delta => delta > 0
)
onValidIncrement(delta => console.log(`Valid increment by ${delta}`))
onInvalidIncrement(delta => console.log(`Please use a number greater than 0`))
...
emitIncrement(2)
// logs "Valid increment by 2"
emitIncrement(0)
// logs "Please use a number greater than 0"
```
--------------------------------
### Create async state with createAsyncSubject
Source: https://github.com/devagrawal09/solid-events/blob/master/README.md
createAsyncSubject manages asynchronous operations, accepting a reactive async function. It automatically resets when the source function reruns. Event handlers can be used to update the derived state, such as filtering results.
```ts
const getBoards = cache(async () => {
"use server";
// fetch from database
}, "get-boards");
export default function HomePage() {
const [onDeleteBoard, emitDeleteBoard] = createEvent();
const boards = createAsyncSubject(
() => getBoards(),
onDeleteBoard(
(boardId) => (boards) => boards.filter((board) => board.id !== boardId)
)
);
...
}
```
=== COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.