Skip to content

Releases: MZanggl/promistate

usePromistate improvements

24 Jan 12:32
Compare
Choose a tag to compare

React's version of promistate now allows passing a dependencies array to update the callback in case it depends on local state (same as React's useCallback).

const [search, setSearch] = React.useState('')

usePromistate(() => fetchArticles(search), {}, [search])

Additionally, some types have been improved.

Add delay option & isDelayOver field

22 Oct 12:18
Compare
Choose a tag to compare

By checking the new field isDelayOver in conjunction with isPending, this lets you avoid flashing loading spinners for fast requests.

This release adds

  • new field isDelayOver to the result of promistate.
  • new option delay: Specifies after how many ms isDelayOver will be set to true. Defaults to 200ms.

Programmatically set error

13 Sep 07:47
Compare
Choose a tag to compare

Sometimes you may wish to set the error programmatically, unrelated to the actual promise.

import promistate from 'promistate'

const promise = promistate(() => fetch('...'))

promise.error = new Error('internal error')

or with the react hook:

import { usePromistate } from 'promistate/lib/react'

const [promise, actions] = usePromistate(() => fetch('...'))

actions.setError(new Error('internal error'))

listen API & React Hooks support

26 Jun 23:57
Compare
Choose a tag to compare

Added

listen API

There is a small but powerful new listen API to catch any state changes. This allows promistate to be used outside of vue-like reactivity systems ( vue, alpine or angular). It opens promistate up for use in react.js, svelte and EVEN Vanilla JS (see README for examples, more coming...).

React hooks support

Thanks to the listen API, promistate now has first-class support for react. Here is an example

import React from "react";
import { usePromistate } from "promistate/lib/react";

export default function App() {
  const [todosPromise, todoActions] = usePromistate(somePromise);
  // todosPromise.value, todosPromise.isPending, ...
  // todoActions.load(), todoActions.reset(), todoActions.setValue('new Value')
}

Fixes

  • Mutating a value directly was previously not causing stale loads to be ignored when ignoreStaleLoad was enabled

Add option to ignore stale promise loads + cancelling promises

25 Jun 12:18
Compare
Choose a tag to compare

Added

ignoreStaleLoad option

Imagine you have a button "send request". Sending the request will make a new button appear to cancel the request again. When you cancel the request, you can again click "send request".

This comes with two complexities

  1. Canceling the request should not change the state once the promise settles
  2. Requesting > canceling (reset) > requesting should not change the state with the result of the first request, only with the result of the second request

Pass { ignoreStaleLoad: true } in the configurations and you are good to go. promistate takes it from here.

This way, when on cancel you call the "reset" method it will ignore any previously pending promise once they settle. Same way if you call "load" twice (or load, reset, load), the first "load" will be completely ignored).

Fixed

Previously I was not exposing the types we used, which makes it hard to build on top of promistate (e.g. for a react hook, which will come soon)

Added timesSettled & resolve synchronous callbacks

22 Jan 13:06
Compare
Choose a tag to compare

Added

"timesSettled" is a new member of the state and it holds a count how many times load() was settled.

Fixed

Code like this crashed

promistate(id => {
  return id ? fetch('...') ? null
})

because it was expected that the callback always returns a promise.

Breaking change: import

15 Jan 12:53
Compare
Choose a tag to compare

Import changed from

import { promistate, Status } from 'promistate

to

import promistate, { PromistateStatus } from 'promistate

make isEmpty an accessor so it reacts to value mutations

05 Jan 06:03
Compare
Choose a tag to compare

See test for details

test('isEmpty reacts to value changes', async (assert) => {
    const state = promistate(() => [], { defaultValue: [1] })
    assert.isFalse(state.isEmpty)

    state.value = []
    assert.isTrue(state.isEmpty)
})

Custom isEmpty check & proper context binding

04 Jan 13:27
Compare
Choose a tag to compare
  • Feature: New configuration to pass a custom isEmpty check. This is useful if the response is something like { page: 1, items: [] }
  • Bugfix: Bind the context of promistate result to the callback method. This is useful if you need to append a response to the previous one, or pass parts of it in the request (e.g. page token)