Releases: hazae41/glacier
1.0.81 - The optimistic loop update
CHANGES
- Update generator now can yield multiple optimistics:
user.update(async function* () {
yield { data: "Naive optimistic data" } // data that we create on-the-fly from what we suppose it will look like
const tx = await contract.doSomething(user.data) // make an Ethereum transaction
yield { data: getUserDataFromLogs(tx) } // data that we expect before the transaction is mined
const txr = await tx.wait() // wait for transaction mined
}, { timeout: 60 * 1000 })
1.0.80 - The optimistic fetch update
CHANGES
- You can now return nothing in your updater in order to use the regular fetcher:
document.update(async function* () {
yield { data: "My optimistic document" }
await new Promise(ok => setTimeout(ok, 5000))
// no return, will use the fetcher to get the new state
})
This is useful when you know the resource will be updated but want to display an optimistic state.
Also, { cache: "reload" }
will be passed to the fetcher in order to skip the cache, feel free to pass it to JS fetch or Axios or ignore it
1.0.77 - The update params update
BREAKING CHANGES
- Mutations are now locked while an optimistic update is ongoing
- You can pass custom timeout, expiration, cooldown to update:
update(updater, params, aborter)
await document.update(async function* (previous) {
yield { data: "My optimistic document" }
return await postAsJson("/api/edit", "My updated document")
}, { timeout: 60 * 1000 })
CHANGES
- Better error logging when aborted or timed out
1.0.74 - The generated optimistic update
BREAKING CHANGES
- New optimistic API with more control, just use "yield" with your optimistic state, which will be replaced if success or reverted if error
document.update(async function* (previous) {
yield { data: "My optimistic document" }
return await postAsJson("/api/edit", "My document")
})
1.0.73 - The breaking update
BREAKING CHANGES
- Removed N type parameter, just use
Data | Ref
in your first type parameter
BEFORE: XSWR.single<Data, Error, Ref>(...)
NOW: XSWR.single<Data | Ref, Error>(...)
- Removed ParamsContext, for avoiding nasty bugs when you use a schema that's in another branch of the params tree. You can still use params in CoreContext for global params
- Removed Normal in favor of a new normalization pattern with more control and more type safety
async function getDataRef(data: Data | Ref, more: XSWR.NormalizerMore) {
if ("ref" in data) return data
const schema = getDataSchema(data.id)
await schema.normalize(data, more)
return { ref: true, id: data.id } as Ref
}
See the docs for more details
CHANGES
- Fixed comparison bug when calling
first()
on a normalized scrolling resource
1.0.71 - The Suspense update
BREAKING CHANGES
- fetch, refetch, first and scroll now throw on SSR
CHANGES
- Added
handle.suspend()
a super natural and easy way to suspend your components
function Component() {
const { data, error, suspend } = useData()
// Throw the error
if (error) throw error
// Fetch and suspend until next state change
if (!data) throw suspend()
return <div>{JSON.stringify(data)}</div>
}
That's it, you have control over when you suspend and when your throw 🚀
- Fixed bugs and simplified code
1.0.69 - The lazy update
BREAKING CHANGES
- Scroll resources now need to have a Normalized type that extends the Data type
To put it another way, your Data type must have an union with your data and your normalized data:
return XSWR.scroll<Data | string, Error, string>(url, fetcher)
This is because on scroll, previous pages are in normalized form, but the next page is in data form
newData = [...previousPages: Normalized[], nextPage: Data]
CHANGES
- Object states are now lazy initialized on fetch(), mutate(), refetch(), scroll(), update()
- Fixed bugs
- Fixed types
1.0.64 - The synchronization update
BREAKING CHANGES
make()
,Schema.make()
and Object constructors no longer needinit
parameter, they will get data only once!mutate()
now accepts a function
mutate((currentState?: State) => State | undefined)
CHANGES
- Improved handles synchronization, no longer double gets
- Handles no longer require a memoized fetcher and static params
- Handle and object methods will now wait for state initialization, no more need for ready check
- Handles and schemas now accept an undefined fetcher;
fetch()
andrefetch()
will just return the current state - Simplified state mutation mechanism, 0% weird behaviour
- Added a test for complex and nested store normalization
1.0.60 - The normalization update
BREAKING CHANGES
- All type parameters now follow the order
D,E,N,K
; some types may break if you used type parameters before
CHANGES
- Added store normalization, out of the box, no dependency needed
Example
We'll use normalization for an array that contains items of type Data, each with an unique id
interface Data {
id: string
name: string
}
First, create a schema factory for an item
function getDataSchema(id: string) {
return XSWR.single<Data>(`/api/data?id=${id}`, fetchAsJson)
}
Then, create a normal for an item
A normal is an object that encapsulates your data, its schema, and a reference to your data (so we can delete the original data and just keep the reference)
function getDataNormal(data: Data) {
return new XSWR.Normal(data, getDataSchema(data.id), data.id)
}
Then, create a schema for your container, and create a normalizer, it will return then new structure of your container
In this case, all the array is mapped to normals, which will then automatically be replaced by references by XSWR
function getAllDataSchema() {
function normalizer(data: Data[]) {
return data.map(getDataNormal)
}
return XSWR.single<Data[], Error, string[]>(
`/api/data/all`,
fetchAsJson,
{ normalizer })
}
Notice the extra type parameter string[]
, it's the final type of our container, after normalization
That's it! No dependency needed, it just works!
You can find a full example in test/next/normalizer
1.0.59 - The maker update
NO BREAKING CHANGES
CHANGES
make
,Schema.make
, and Object constructors now acceptinitialize
as last optional parameter (default true) in order to initialize the object with the current state, it can be set to false for optimizing performances when you just need to callmutate
and don't need the data, for example
const object = make(getHelloSchema(), false) // Won't load the state in the object
await object.mutate({ data: "Hello World" })