- commit
- bade988
- parent
- 351a8d3
- author
- Eric Bower
- date
- 2024-08-17 01:10:15 +0000 UTC
docs: copy
6 files changed,
+139,
-18
+10,
-0
1@@ -45,6 +45,11 @@ func main() {
2 Href: "/endpoints",
3 Page: pager("endpoints.md"),
4 },
5+ {
6+ Text: "Dispatch",
7+ Href: "/dispatch",
8+ Page: pager("dispatch.md"),
9+ },
10 },
11 },
12 {
13@@ -63,6 +68,11 @@ func main() {
14 Href: "/schema",
15 Page: pager("schema.md"),
16 },
17+ {
18+ Text: "Selectors",
19+ Href: "/selectors",
20+ Page: pager("selectors.md"),
21+ },
22 },
23 },
24 {
+62,
-0
1@@ -0,0 +1,62 @@
2+---
3+title: Dispatch
4+description: How to activate controllers
5+---
6+
7+We use the term `dispatch` when we are emitting an event with a specific type
8+signature
9+([flux standard action](https://github.com/redux-utilities/flux-standard-action)).
10+
11+There are two ways to activate a thunk: by dispatching an action or calling it
12+within another thunk.
13+
14+The type signature of `dispatch`:
15+
16+```ts
17+type Dispatch = (a: Action | Action[]) => any;
18+```
19+
20+Within `starfx`, the `dispatch` function lives on the store.
21+
22+```ts
23+const { createSchema, createStore } from "starfx";
24+const [schema, initialState] = createSchema();
25+const store = createStore({ initialState });
26+
27+store.dispatch({ type: "action", payload: {} });
28+```
29+
30+You can also use dispatch with a `react` hook:
31+
32+```tsx
33+import { useDispatch } from "starfx/react";
34+
35+function App() {
36+ const dispatch = useDispatch();
37+
38+ return <button onClick={() => dispatch({ type: "click" })}>Click me!</button>;
39+}
40+```
41+
42+# Listening to actions
43+
44+This is a pubsub system after all. How can we listen to action events?
45+
46+```ts
47+import { take } from "starfx";
48+
49+function* watch() {
50+ while (true) {
51+ const action = yield* take("click");
52+ // -or- const action = yield* take("*");
53+ // -or- const action = yield* take((act) => act.type === "click");
54+ // -or- const action = yield* take(["click", "me"]);
55+ console.log(action.payload);
56+ }
57+}
58+
59+store.run(watch);
60+```
61+
62+`watch` is what we call a [supervisor](/supervisors). Click that link to learn
63+more about how they provide powerful flow control mechanisms.
+22,
-16
1@@ -30,22 +30,28 @@ It all happens as a single unidirectional loop.
2
3 `starfx` is different in a number of ways.
4
5-First, we combine both state and side-effect management into a single cohesive
6-unit. This streamlines the implementation of your web app.
7-
8-Second, business logic does not live inside of `react`, rather, it lives inside
9-of the side-effect system. We are not shackled by `react` lifecycle hooks, in
10-fact, `starfx` has virtually no concept of `react` at all -- except for a couple
11-of hooks. Then entire system is designed, from the ground up, to not need
12-`react` at all in order to function. At the end of the day, `starfx` works by
13-subscribing to and publishing events. Those events could come from `react`, but
14-they could also come from anywhere.
15-
16-Thirdly, we have taken the best part about `express` and `koa` and applied it to
17-fetching API data on the front-end. What this means is that we have a powerful
18-middleware system that we can leverage on the front-end.
19-
20-# Why does `starfx` use js generators?
21+We combine both state and side-effect management into a single cohesive unit.
22+This streamlines the implementation of your web app.
23+
24+Our business logic does not live inside of `react`, rather, it lives inside of
25+the side-effect system. We are not shackled by `react` lifecycle hooks, in fact,
26+`starfx` has virtually no concept of `react` at all -- except for a couple of
27+hooks. The entire system is designed, from the ground up, to not need `react` at
28+all in order to function. At the end of the day, `starfx` works by subscribing
29+to and publishing events. Those events could come from `react`, but they could
30+also come from anywhere.
31+
32+We have taken the best part about `express` and `koa` and applied it to fetching
33+API data on the front-end. What this means is that we have a powerful middleware
34+system that we can leverage on the front-end.
35+
36+We built a state management system leveraging the concept of a database schema.
37+We took inspiration from [zod](https://zod.dev) to build an ergonomic and
38+powerful state system leveraging reusable slice helpers. With our schema and
39+custom built store, we can replace all of boilerplate with a single function
40+call `createSchema()`.
41+
42+# Why does `starfx` use [generators](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Generator)?
43
44 Generators give us -- the library authors -- more control over how side-effects
45 are handled within a javascript runtime environment. There are things that we
+41,
-0
1@@ -0,0 +1,41 @@
2+---
3+title: Selectors
4+Description: Deriving data with selectors
5+---
6+
7+In a typical web app, the logic for deriving data is usually written as
8+functions we call selectors.
9+
10+The basic function signature of a selector:
11+
12+```ts
13+const selectData = (state: WebState) => state.data;
14+```
15+
16+Selectors are primarily used to encapsulate logic for looking up specific values
17+from state, logic for actually deriving values, and improving performance by
18+avoiding unnecessary recalculations.
19+
20+To learn more, redux has excellent docs
21+[on deriving data with selectors](https://redux.js.org/usage/deriving-data-selectors).
22+
23+There is 100% knowledge transfer between selectors in `starfx` and `redux`
24+because we adhere to the same function signature.
25+
26+The only difference is that as part of our API we re-export
27+[reselect.createSelector](https://reselect.js.org/api/createselector/), which
28+will memoize functions:
29+
30+```ts
31+import { createSelector } from "starfx";
32+
33+const selectData = (state) => state.data;
34+const myselector = createSelector(
35+ selectData,
36+ (data) => data.sort((a, b) => a.id - b.id);
37+);
38+```
39+
40+Function memoization is just a way to cache a function call. If the dependencies
41+(e.g. the result of `selectData`) don't change, then `myselector` will not be
42+called: it will return its previous value.
+3,
-1
1@@ -6,7 +6,7 @@ description: Learn how supervisor tasks work
2 A supervisor task is a way to monitor children tasks and probably most
3 importantly, manage their health. By structuring your side-effects and business
4 logic around supervisor tasks, we gain very interesting coding paradigms that
5-result is easier to read and manage code.
6+result in easier to read and manage code.
7
8 [Supplemental reading from erlang](https://www.erlang.org/doc/design_principles/des_princ)
9
10@@ -14,6 +14,8 @@ The most basic version of a supervisor is simply an infinite loop that calls a
11 child task:
12
13 ```ts
14+import { call } from "starfx";
15+
16 function* supervisor() {
17 while (true) {
18 try {
+1,
-1
1@@ -50,7 +50,7 @@ export interface FxStore<S extends AnyState> {
2 reset: (ignoreList?: (keyof S)[]) => Operation<UpdaterCtx<S>>;
3 run: ReturnType<typeof createRun>;
4 // deno-lint-ignore no-explicit-any
5- dispatch: (a: AnyAction) => any;
6+ dispatch: (a: AnyAction | AnyAction[]) => any;
7 replaceReducer: (r: (s: S, a: AnyAction) => S) => void;
8 getInitialState: () => S;
9 // deno-lint-ignore no-explicit-any