Last active
June 18, 2023 04:17
-
-
Save brettinternet/5968fdf2e229e4ef0cfdcff22ff24a50 to your computer and use it in GitHub Desktop.
Derive data result from nullable with data selection - useful when you use react query as a state tool
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Nullable user example: | |
type MaybeUser = UserQuery['user'] | |
/** | |
* Possibly null user, such as on an auth page | |
* Here's a description on why these overloads are required: https://stackoverflow.com/a/67640634 | |
*/ | |
export function useMaybeUser<UserData = MaybeUser>( | |
select: (user: MaybeUser) => UserData | |
): UserData | |
export function useMaybeUser(select?: undefined): MaybeUser | |
export function useMaybeUser<UserData = MaybeUser>( | |
select?: (user: MaybeUser) => UserData | |
): UserData | MaybeUser | |
export function useMaybeUser<UserData = MaybeUser>( | |
select?: (user: MaybeUser) => UserData | |
): UserData | MaybeUser { | |
return useUserQuery(gqlClient, {}, { select }).data | |
} | |
const Component: React.FC = () => { | |
const userId = useMaybeUser(user => user?.id) | |
if (userId) { | |
return <User id={userId} /> | |
} | |
return null | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Non nullable user example: | |
type User = NonNullable<UserQuery['user']> | |
/** | |
* Returns non nullable value in a nested part of the React tree where you're sure to have the data | |
*/ | |
export function useUser<UserData = User>( | |
selectUser: (user: User) => UserData | |
): UserData | |
export function useUser(select?: undefined): User | |
export function useUser<UserData = User>( | |
selectUser?: ((user: User) => UserData) | undefined | |
): UserData | User | |
export function useUser<UserData = User>( | |
selectUser?: ((user: User) => UserData) | undefined | |
): UserData | User { | |
const select = useCallback( | |
(user: User) => { | |
if (!user) { | |
throw Error('User not found.') | |
} | |
if (select) { | |
return select(user) | |
} | |
return user | |
}, | |
[selectUser] | |
) | |
const user = useUserQuery(gqlClient, {}, { select }).data | |
if (!user) { | |
throw Error('User not found.') | |
} | |
return user | |
} | |
// `useUserQuery` is queried higher up in the react tree, so data should be present at this level | |
const Component: React.FC = () => { | |
// Now, despite being nullable, user arg and return values will be non null in the select callback | |
const userId = useUser(user => user.id) | |
return <User id={userId} /> | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment