Replies: 8 comments 26 replies
-
Big fan of this proposal, I really like the deterministic way that react-query and swr represents state. As for caching ens I would worry that caching it in local storage could create a lot of complexity in when to expire the cache or revalidate as technically the ens name and avatar could be updated at any time independent of the app lifecycle. |
Beta Was this translation helpful? Give feedback.
-
Some excellent thinking here. I’m a big fan of react-query and how it gives much more granularity to represent the lifecycle of a query/mutation. Having deterministic states will help build some really elegant UI that’s very declarative and easy to reason about. My concern is the same as @sammdec’s, you’re then bundling in a (by no means) small dependency in with wagmi. If you already have react-query or SWR it could get funky having two query providers in your app. The concepts should certainly be borrowed though! Quick aside: another thing I really like about the react-query hooks is the ability to couple callbacks with the hook itself, something along these lines: const [state, connect] = useConnect({
// keep additional logic involving connecting wallets coupled with the hook
onConnected: wallet => {
// do something on connect
},
onError: error => {
// handle the error
}
}) Storing the address + ENS in localstorage could be a great optional thing to have, but I probably wouldn’t want that as a default behaviour (e.g. what would happen if I closed the tab, changed accounts and came back again… it could feel choppy vs. handling the |
Beta Was this translation helpful? Give feedback.
-
Love this discussion. Major props @jxom for kicking things off. 1. Finite & deterministic statesWe should do this. I'm a proponent of API standardization. Learn how one wagmi hook works (especially hooks related to data fetching) and apply that knowledge to working with others. It would be great if there was a core Non-data-fetching hooks should also implement these or similar domain specific states (a la @jxom's 2. Cache what we can, where we canThis would be a boon for user experience (and Alchemy/Inufra bills lol). Like others mentioned, there are a few ideas: use local storage, add third-party lib to the core (react-query/swr), implement our own cache. It could be interesting to approach this by using different package entrypoints for the hooks: import { useEnsLookup } from 'wagmi'
import { useEnsLookup } from 'wagmi/swr'
import { useEnsLookup } from 'wagmi/react-query' While the wagmi core @jxom @gosseti @sammdec any thoughts? (anyone else welcome to chime in to!) Some more granular details to chat about:
|
Beta Was this translation helpful? Give feedback.
-
Love this thinking @jxom, thank you! Two other options that spring to mind (I'm not sure if they're good ideas!):
it's been a while since I did anything like this, but this kind of pattern: https://matiasklemola.com/typescript-union-types interface NotAsked {
type: 'NotAsked'
}
interface Loading {
type: 'Loading'
}
interface Success<T> {
type: 'Success'
data: T
}
interface Failure<E> {
type: 'Failure'
error: E
}
type RemoteData<T, E> = NotAsked | Loading | Success<T> | Failure<E>
kinda tangent, but I'm also curious if there's a standardized way we could merge states from multiple queries, e.g. I've been doing something like this const [{ loading: accountLoading }] = useAccount()
const [{ loading: messageLoading }] = useSignMessage()
// any : boolean[] -> boolean
const loading = any([ accountLoading, messageLoading, ... ]) |
Beta Was this translation helpful? Give feedback.
-
update to my last point about combining states - I think you could do something like this (pseudocode!) type Predicate = (data: RemoteData) => bool
isLoading: Predicate = (data) => data.type === 'Loading'
any = (pred: Predicate, xs: RemoteData) => bool;
any(isLoading, [fooLoading, barLoading]) |
Beta Was this translation helpful? Give feedback.
-
An RFC for this has been posted here: #153 |
Beta Was this translation helpful? Give feedback.
-
A bit of an update: We now have an active development branch for the new Right now, we are working on migrating the wagmi (react) package to #247 as per this proposal. If anyone wants to help with a swr adaptor, or even a svelte or vue client for wagmi, feel free to reach out! With the new foundation of |
Beta Was this translation helpful? Give feedback.
-
wagmi 0.3 has been released, introducing:
|
Beta Was this translation helpful? Give feedback.
-
Yo!
So this lib is actually amazing, and very well thought out in terms of it's architecture. I'm really loving and enjoying using it too!
This library makes use of async logic (ens lookup, obtaining balance, switching networks, etc) quite a lot, and I have a few ideas to make the user experience even better:
1. Finite & deterministic states
At the moment, states in this library are implicit & indeterministic, meaning that it is not possible to retrieve a finite state from the values exposed from the hooks, which could lead to UX bugs. At the moment, we can represent async state via the following values:
loading
is the "loading" state, and is obviously explicitly represented,data
is the "success" state, and it represented implicitly throughdata
.error
is the "error" state, and it represented implicitly througherror
.Representing async state via these values works, but can lead to the following issue:
There is no idle state & implicit states can be confusing
Some hooks don't automatically invoke, so at the moment, if we wish to represent an "idle" state with the exposed hook values, it would be achieved like so:
which does look a bit confusing to me, and consumers could be bound to representing idle state like so if they are not careful, that could lead to UX quirks:
It would be nice if we can represent all possible states with a set of finite & deterministic state variables. There could be state variables such as
isIdle
,isLoading
,isSuccess
&isError
(which are deterministic, meaning only one can be truthy at a time, they can't overlap). This API is similar to react-query too.This makes render logic cleaner, and easier to follow:
For some hooks, this terminology might not make sense, e.g.
isIdle
may not make sense foruseConnect
. We could make it more specific to "connecting" to a wallet?2. Cache what we can, where we can
I really think there is room for improvement with the initial state UX for connecting to a wallet. I feel that most dapps these days have a "flash of loading wallet/resolving ens" experience, and if we can solve that issue in this lib, then that would be awesome.
At the moment, we see this "flash of loading wallet/resolving ens", which seems a bit jarring:
I think it would be nice if we could try to cache what we can, where we can. In this circumstance, I think it could be possible to cache stuff like account address, ens, avatar, balances, etc in local storage, and then display the data from local storage straight away when the user navigates back to the dapp. Representing this in the current API could be hard, as I feel like there should be a flag to indicate that the wallet is currently in a state of reconnecting. In the proposed API, this could be possible via the
isReconnecting
flag. Below is a diagram to represent a possible flow foruseConnect
:I think this could be achievable integrating w/ an async state lib like react-query or swr, and utilise it for our async functions (also means we don't have to deal with caching as well as setting loading/success/error state as react-query/swr handles this internally).
Anyway, that's my idea & proposal!
What are your thoughts on this? Do you have any ideas?
Also, I am more than happy to contribute!
Beta Was this translation helpful? Give feedback.
All reactions