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```