Skip to content

Docs: clarify actions vs. reduce - #274

Merged
matthewp merged 1 commit into
mainfrom
docs-actions-reducers
Oct 5, 2026
Merged

matthewp merged 1 commit into
mainfrom
docs-actions-reducers

Conversation

@matthewp

@matthewp matthewp commented Oct 5, 2026

Copy link
Copy Markdown
Owner

Fixes #266

The docs said actions update context and must always return it. In the code, action(fn) is reduce((ctx, ev) => (fn(ctx, ev), ctx)), so the function's return value is thrown away and context passes through unchanged.

Changes

  • Understanding Actions (concepts-actions.md), mostly rewritten:
    • action is for side effects and its return value is ignored. reduce is how you update context, and its return value becomes the new context.
    • Removed every return ctx from action examples, and converted context-updating actions to reduce.
    • Rewrote the pitfalls. They had it backwards: "always return context from actions" is now "don't return context from actions" and "always return from reducers".
    • Corrected the execution-order example, which relied on actions passing context along.
    • Replaced "Mutating Context: never do this" with what actually happens. An action receives the context object itself, so mutating it works; the page now says so but still recommends reduce with a new object. test-invoke.js depends on this behavior.
    • Fixed "Testing Actions". It called reduce(...) as if it were a function, but reduce returns a descriptor object.
  • action / reduce API pages: say what happens to the return value, and that reducers and actions run in order.
  • Core Concepts: the "Putting It All Together" example now uses reduce. It also had two bugs that made it throw: it wrapped a guard in guard() again, and it passed context as an object instead of a function.
  • Transitions: the execution-order list now shows context updating before the state change, matching transitionTo.
  • Guards: the issue flagged "Guards see the old context (before actions modify it)". That statement is correct, since guards run before any reducer in the transition (machine.js:160). I reworded it to say "before any reducers update it".

Verification

  • Ran the Core Concepts example and a script exercising the documented behavior against packages/core/machine.js. Confirmed that guards see the original context, actions see the context from earlier reducers, action return values are discarded, and mutations made in actions persist.
  • npm run --workspace=docs build passes.

…ntext

action() discards its function's return value, but the docs said actions
update context and must return it. Rewrite the actions guide and update
the action/reduce API pages, core concepts, transitions, and guards pages
to match the implementation. Also fix the core concepts example, which
wrapped a guard in guard() and passed context as an object.

Fixes #266
@changeset-bot

changeset-bot Bot commented Oct 5, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: a2f404b

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@matthewp
matthewp merged commit 3e44dbf into main Oct 5, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Docs: clarify actions and reducers

1 participant