| author | |
| committer | |
| log | b51077c59854543b2c70ea2be825d68cfb567d8c |
| tree | 3449d3519625c9bb4232125795e3004322a32d05 |
| parent | f62d1ee915bf4e77c8e2d55d1286211289fbdd51 |
| signature |
4 files changed, 18 insertions(+), 21 deletions(-)
jsr.json+1-1| ... | ... | @@ -1,6 +1,6 @@ |
| 1 | 1 | { |
| 2 | 2 | "name": "@clo/react-mutation", |
| 3 | "version": "1.0.0-beta.6", | |
| 3 | "version": "1.0.0-beta.7", | |
| 4 | 4 | "exports": { |
| 5 | 5 | ".": "./src/mod.ts", |
| 6 | 6 | "./tanstack-query.ts": "./src/tanstack-query.ts", |
package.json-1| ... | ... | @@ -1,6 +1,5 @@ |
| 1 | 1 | { |
| 2 | 2 | "name": "@clo/react-mutation", |
| 3 | "version": "0.1.0", | |
| 4 | 3 | "private": true, |
| 5 | 4 | "description": "", |
| 6 | 5 | "license": "ISC", |
readme.md+9-9| ... | ... | @@ -21,7 +21,7 @@ The primary gains React Mutation provides are |
| 21 | 21 | this power in more detail. |
| 22 | 22 | - Easy debouncing and batching utilities. |
| 23 | 23 | |
| 24 | ## Usage | |
| 24 | ## Setup | |
| 25 | 25 | |
| 26 | 26 | React Mutation starts with a `MutationClient`, which shares global state for an application. |
| 27 | 27 | |
| ... | ... | @@ -61,7 +61,7 @@ export const mutations = new MutationClient({ |
| 61 | 61 | }); |
| 62 | 62 | ``` |
| 63 | 63 | |
| 64 | ### Declaring Mutations | |
| 64 | ## Declaring Mutations | |
| 65 | 65 | |
| 66 | 66 | With a mutation client, you can declare mutations with `mutations.define()`. |
| 67 | 67 | Start with the API call code, and then add an optimistic updater function. |
| ... | ... | @@ -121,7 +121,7 @@ export function Example({ id }: { id: string }) { |
| 121 | 121 | ``` |
| 122 | 122 | |
| 123 | 123 | |
| 124 | ### Optimistic Updates | |
| 124 | ## Optimistic Updates | |
| 125 | 125 | |
| 126 | 126 | The `optimistic` function is given an object with the following APIs |
| 127 | 127 | |
| ... | ... | @@ -132,7 +132,7 @@ The `optimistic` function is given an object with the following APIs |
| 132 | 132 | - `onRestore` - add a callback to revert your optimistic update |
| 133 | 133 | - `onRefetch` - add a callback to fetch data after a success |
| 134 | 134 | |
| 135 | #### React Query Optimistic Helpers | |
| 135 | ### React Query Optimistic Helpers | |
| 136 | 136 | |
| 137 | 137 | When using React Query, you can opt into some incredible helpers for making it |
| 138 | 138 | very easy to write Optimistic Updates. Our setup at work is with this client |
| ... | ... | @@ -191,7 +191,7 @@ automatically implement `onRefetch` and `onRestore` callbacks. The current list |
| 191 | 191 | - `objArrayUpdate` - update items in array by `filter` + `update` |
| 192 | 192 | - `objArrayInsertIndex` - insert an item in an array at an index |
| 193 | 193 | |
| 194 | ### Debouncing | |
| 194 | ## Debouncing | |
| 195 | 195 | |
| 196 | 196 | By default, a mutation will block the UI (by setting isPending). If you add |
| 197 | 197 | `debounceMs`, the mutation will no longer set isPending. Multiple mutations |
| ... | ... | @@ -226,7 +226,7 @@ function Item({ id }: { id: string }) { |
| 226 | 226 | } |
| 227 | 227 | ``` |
| 228 | 228 | |
| 229 | ### Calling Mutations | |
| 229 | ## Calling Mutations | |
| 230 | 230 | |
| 231 | 231 | Three methods exist for calling mutations: |
| 232 | 232 | |
| ... | ... | @@ -234,7 +234,7 @@ Three methods exist for calling mutations: |
| 234 | 234 | - From a React component: `useMutate(mutDoAction)` |
| 235 | 235 | - From a React Element: `<MutationButton>` |
| 236 | 236 | |
| 237 | #### The `useMutate` Hook | |
| 237 | ### The `useMutate` Hook | |
| 238 | 238 | |
| 239 | 239 | The `useMutate(null | Mutation)` react hook returns an object with the following properties. |
| 240 | 240 | |
| ... | ... | @@ -269,7 +269,7 @@ return ( |
| 269 | 269 | ); |
| 270 | 270 | ``` |
| 271 | 271 | |
| 272 | #### Mutation Buttons | |
| 272 | ### Mutation Buttons | |
| 273 | 273 | |
| 274 | 274 | You can wrap your button component with `createMutationButton` to make it support mutations |
| 275 | 275 | |
| ... | ... | @@ -312,7 +312,7 @@ It can now be used for easy mutations: |
| 312 | 312 | |
| 313 | 313 | |
| 314 | 314 | |
| 315 | ### Batched Mutations | |
| 315 | ## Batched Mutations | |
| 316 | 316 | |
| 317 | 317 | Each call to the mutation applies new optimistic state on top of the previous, |
| 318 | 318 | and after a debounce / throttle, the new optimistic state is committed to the |
src/react.ts+8-10| ... | ... | @@ -42,8 +42,7 @@ export type UseMutateResult<Args extends unknown[], Result> = |
| 42 | 42 | export interface UseMutateResultBase<Args extends unknown[], Result> { |
| 43 | 43 | run: (...args: Args) => void; |
| 44 | 44 | runWithOptions: ( |
| 45 | options: RunOptions<Result>, | |
| 46 | ...args: Args | |
| 45 | ..._: [...args: Args, options: RunOptions<Result>] | |
| 47 | 46 | ) => Promise<Result>; |
| 48 | 47 | clear: () => void; |
| 49 | 48 | } |
| ... | ... | @@ -243,10 +242,13 @@ class Observer<Args extends unknown[], Result> { |
| 243 | 242 | return promise; |
| 244 | 243 | } |
| 245 | 244 | |
| 246 | runWithOptions(options: RunOptions<Result>, ...args: Args): void { | |
| 245 | runWithOptions(...array: [...args: Args, options: RunOptions<Result>]): void { | |
| 247 | 246 | const mutation = this.mutation; |
| 248 | 247 | if (!mutation) return; |
| 249 | 248 | |
| 249 | const args = array.slice() as Args; | |
| 250 | const options = args.pop() as RunOptions<Result>; | |
| 251 | ||
| 250 | 252 | this.currentArgs = args; |
| 251 | 253 | const key = mutation.key(args); |
| 252 | 254 | |
| ... | ... | @@ -295,12 +297,8 @@ class Observer<Args extends unknown[], Result> { |
| 295 | 297 | } |
| 296 | 298 | |
| 297 | 299 | binding: UseMutateResult<Args, Result> = ((self: this) => ({ |
| 298 | run(...args) { | |
| 299 | return self.run(...args); | |
| 300 | }, | |
| 301 | runWithOptions(options, ...args) { | |
| 302 | return self.runWithOptions(options, ...args); | |
| 303 | }, | |
| 300 | run: self.run.bind(self), | |
| 301 | runWithOptions: self.runWithOptions.bind(self), | |
| 304 | 302 | clear() { |
| 305 | 303 | self.setState({ |
| 306 | 304 | status: ["error", "success"].includes(self.state.status) |
| ... | ... | @@ -459,8 +457,8 @@ function GenericMutationButton< |
| 459 | 457 | const computedArgs = typeof args === "function" ? args(e) : args; |
| 460 | 458 | if (!computedArgs || e.defaultPrevented) return; |
| 461 | 459 | state.runWithOptions( |
| 462 | { onSuccess, onError, onSettled }, | |
| 463 | 460 | ...computedArgs, |
| 461 | { onSuccess, onError, onSettled }, | |
| 464 | 462 | ); |
| 465 | 463 | }, [state]), |
| 466 | 464 | isPending: state.isPending, |