The return value of the React state hook is an array, used as:
const [state, setState] = React.useState(false);
This way you could use any name for the state and the setter.
In useSWR is an object:
const { data, error } = useSWR(URL, fetch)
Is there a special reason why it's not an array to? Even one of the examples in the website needs to rename data.
const { data: user } = useSWR('/api/user')
const { data: projects } = useSWR(
() => '/api/projects?uid=' + user.id
);
This could have be
const [ user ] = useSWR('/api/user')
const [ projects ] = useSWR(
() => '/api/projects?uid=' + user.id
);
And if you need other values:
const [data, error, isValidating, revalidate] = useSWR(URL, fetch)
I understand this could be a annoying if you want to use revalidate without isValidating or error but I think is more common to need multiple data with different names than reading those other values in isolation.
I understand this could be a annoying if you want to use revalidate without isValidating or error but I think is more common to need multiple data with different names than reading those other values in isolation.
Exactly, const [users, _, _unnecessary, _variables, revalidate] = useSWR('/users') isn't a good API.
I think this would be a better solution:
const [users, { error, isValidating, revalidate }] = useSWR('/users', fetch)
As you can deconstruct error, isValidating and revalidate as needed.
Although I think the current API isn't bad at all,const { data: users } = useSWR('/users') is very readable...
You don鈥檛 need to name ignored values, this should work:
const [data, , , revalidate ] = useSWR(URL, fetch)
This is really a matter of preference. Neither of the worst case of both approaches:
const [data, , , revalidate] = useSWR()
const { data: newName, revalidate } = useSWR()
feel particularly difficult to use.
An array approach feels more like a "hook". But as we develop the API and potentially add more information to the response object, the array approach may become unmanageable.
I personally don't find it easy to have to remember how many commas to type, or which position in the array a variable is in.
Not that I'm advocating for it, as I don't care for the pattern, but there's also the possibility of returning both.
You don鈥檛 need to name ignored values, this should work:
const [data, , , revalidate ] = useSWR(URL, fetch)
that looks horrible though and uncomprehensive for someone seeing the code for the first time.
React team implements react hooks in this way, cause always we will need value and its setter and naming will be not important. The problem is coming when we have many optional params like here. So I think your decision was good 馃憤
I like the way some libs like react-i18next do by returning an array with properties. This way you can decide which one to use depending of your usage : const [users] = useSWR() or const { data, revalidate } = useSWR().
See https://github.com/i18next/react-i18next/blob/master/src/useTranslation.js#L81-L84
With @apollo/react-hooks I don't bother with destructuring the return value:
cost fooQuery = useQuery(...)
// extract what we need, but be aware that `query.data` might not exist
const foo = query.data?.foo
if (fooQuery.error) {
return <Error>{...}</Error>
}
if (fooQuery.loading) {
return <Loader>{...}</Loader>
}
return <h1>Hello, {foo}</h1>
That being said, I would much more prefer an object as the return value.
Closing as I think we've reached a happy conclusion :)
Thanks everyone for the discussion.
Most helpful comment
This is really a matter of preference. Neither of the worst case of both approaches:
feel particularly difficult to use.
An array approach feels more like a "hook". But as we develop the API and potentially add more information to the response object, the array approach may become unmanageable.
I personally don't find it easy to have to remember how many commas to type, or which position in the array a variable is in.