repos / starfx

supercharged async flow control library.
git clone https://github.com/neurosnap/starfx.git

starfx / docs / posts
Eric Bower · 16 Aug 24

react.md

  1---
  2title: React
  3description: How to integrate with React
  4toc: 2
  5---
  6
  7Even though we are **not** using `redux`, if you are familiar with
  8[react-redux](https://react-redux.js.org) then this will be an identical
  9experience because `starfx/react` has an identical API signature.
 10
 11`useDispatch`, `useSelector`, and `createSelector` are the bread and butter of
 12`redux`'s integration with `react` all of which we use inside `starfx`.
 13
 14```tsx
 15import {
 16  TypedUseSelectorHook,
 17  useApi,
 18  useSelector as useBaseSelector,
 19} from "starfx/react";
 20import { schema, WebState } from "./store.ts";
 21import { fetchUsers } from "./api.ts";
 22
 23const useSelector: TypedUseSelectorHook<WebState> = useBaseSelector;
 24
 25function App() {
 26  const users = useSelector(schema.users.selectTableAsList);
 27  const api = useApi(fetchUsers());
 28
 29  return (
 30    <div>
 31      {users.map((u) => <div key={u.id}>{u.name}</div>)}
 32      <div>
 33        <button onClick={() => api.trigger()}>fetch users</button>
 34        {api.isLoading ? <div>Loading ...</div> : null}
 35      </div>
 36    </div>
 37  );
 38}
 39```
 40
 41# Hooks
 42
 43## `useSelector`
 44
 45Query your store with this hook.
 46
 47```tsx
 48import { useSelector } from "starfx";
 49
 50function App() {
 51  const data = useSelector((state) => state.data);
 52  return <div>{data}</div>;
 53}
 54```
 55
 56[See `react-redux` docs](https://react-redux.js.org/api/hooks#useselector)
 57
 58## `useDispatch`
 59
 60Call thunks and endpoints with this hook.
 61
 62```tsx
 63import { useDispatch } from "starfx";
 64
 65function App() {
 66  const dispatch = useDispatch();
 67
 68  return (
 69    <button onClick={() => dipatch({ type: "action!" })}>
 70      Click me!
 71    </button>
 72  );
 73}
 74```
 75
 76[See `react-redux` docs](https://react-redux.js.org/api/hooks#usedispatch)
 77
 78## `useLoader`
 79
 80Will accept an action creator or action and return the loader associated with
 81it.
 82
 83```tsx
 84import { useLoader } from "starfx/react";
 85
 86const log = thunks.create<string>("log");
 87
 88function App() {
 89  // this will grab loader for any `log` thunks dispatched
 90  // `action.payload.name`
 91  const loaderAny = useLoader(log);
 92  // this will grab loader a specific `log` thunk dispatched
 93  // `action.payload.key`
 94  const loader = useLoader(log("specific thunk"));
 95}
 96```
 97
 98## `useApi`
 99
100Will take an action creator or action itself and fetch the associated loader and
101create a `trigger` function that you can call later in your react component.
102
103This hook will _not_ fetch the data for you because it does not know how to
104fetch data from your redux state.
105
106```ts
107import { useApi } from 'starfx/react';
108
109import { api } from './api';
110
111const fetchUsers = api.get('/users', function*() {
112  // ...
113});
114
115const View = () => {
116  const { isLoading, trigger } = useApi(fetchUsers);
117  useEffect(() => {
118    trigger();
119  }, []);
120  return <div>{isLoading ? : 'Loading' : 'Done!'}</div>
121}
122```
123
124## `useQuery`
125
126Uses [useApi](#useapi) and automatically calls `useApi().trigger()`
127
128```ts
129import { useQuery } from 'starfx/react';
130
131import { api } from './api';
132
133const fetchUsers = api.get('/users', function*() {
134  // ...
135});
136
137const View = () => {
138  const { isLoading } = useQuery(fetchUsers);
139  return <div>{isLoading ? : 'Loading' : 'Done!'}</div>
140}
141```
142
143## `useCache`
144
145Uses [useQuery](#usequery) and automatically selects the cached data associated
146with the action creator or action provided.
147
148```ts
149import { useCache } from 'starfx/react';
150
151import { api } from './api';
152
153const fetchUsers = api.get('/users', api.cache());
154
155const View = () => {
156  const { isLoading, data } = useCache(fetchUsers());
157  return <div>{isLoading ? : 'Loading' : data.length}</div>
158}
159```
160
161## `useLoaderSuccess`
162
163Will activate the callback provided when the loader transitions from some state
164to success.
165
166```ts
167import { useApi, useLoaderSuccess } from "starfx/react";
168
169import { api } from "./api";
170
171const createUser = api.post("/users", function* (ctx, next) {
172  // ...
173});
174
175const View = () => {
176  const { loader, trigger } = useApi(createUser);
177  const onSubmit = () => {
178    trigger({ name: "bob" });
179  };
180
181  useLoaderSuccess(loader, () => {
182    // success!
183    // Use this callback to navigate to another view
184  });
185
186  return <button onClick={onSubmit}>Create user!</button>;
187};
188```