-
Notifications
You must be signed in to change notification settings - Fork 123
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Feature] Add userServerEffect
to SDK
#664
Conversation
Also add the ability to serialize all the useServerEffectHooks
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
General notes:
object
means an empty object with no properties. If you want an object with arbitrary properties, useRecord<string, unknown>
.{}
andObject
mean anything exceptnull
/undefined
. Not just objects. Yeah, confusing!any
means "I don't want to do type checking any more", and allows things that should be errors. Preferunknown
to say "I don't know, but still keep me safe!"Record<string, unknown>
is equivalent to{[key: string]: unknown}
. Just different syntax for different use cases.[]
ornever[]
means "an empty array".- Does
@types/react
define any helper types that we can use, rather than defining our own?
req: object | undefined // Get type from runtime? | ||
res: object | undefined // Get type from runtime? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
req: object | undefined // Get type from runtime? | |
res: object | undefined // Get type from runtime? | |
req?: object // Get type from runtime? | |
res?: object // Get type from runtime? |
req: object | undefined
means "req
must be defined, but might be explicitly set to undefined
(i.e. {req: undefined}
).
req?: object
means "req
may or may actually be there" (i.e. {}
).
params: {[key: string]: string} | ||
req: object | undefined // Get type from runtime? | ||
res: object | undefined // Get type from runtime? | ||
[key: string]: object | string | number // This accounts for all the `extraGetPropsArgs` values. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[key: string]: object | string | number // This accounts for all the `extraGetPropsArgs` values. | |
[key: string]: object | string | number | undefined // This accounts for all the `extraGetPropsArgs` values. |
Need undefined
in the index signature if you have optional properties. 😉
import AppConfig from '../../universal/components/_app-config' | ||
|
||
export interface GetPropsArgs { | ||
location: Location |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[Educational aside] The type Location
is inherited from TypeScript's built-in DOM library.
type ServerEffectState = { | ||
data: object; | ||
loading: boolean; | ||
error: Error; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
type ServerEffectState = { | |
data: object; | |
loading: boolean; | |
error: Error; | |
} | |
type ServerEffectState<T extends object> = { | |
data: T; | |
loading: boolean; | |
error: Error; | |
} |
Use a generic, otherwise data
is just an empty object.
// Type Definitions | ||
type ServerEffectState = { | ||
data: object; | ||
loading: boolean; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SCAPI hooks use isLoading
, rather than loading
. May want consistency, one way or the other.
* @returns | ||
*/ | ||
export const resolveAllEffects = async () => { | ||
const allData = await Promise.all(contexts.map((resolver) => resolver())) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const allData = await Promise.all(contexts.map((resolver) => resolver())) | |
const allData = await Promise.all(contexts.map(async (resolver) => resolver())) |
If we somehow end up with a sync resolver
that throws an error, using an async
method automatically converts that thrown error into a rejected promise. (Not sure if that's something we need to worry about, though.)
} | ||
type DidUpdateFn = (serverEffectArgs: GetPropsArgs) => Promise<any> | ||
type EffectsResolver = () => Promise<{[x: string]: {}}> | ||
type Provider = ({ children, value }: { children: any; value: any; }) => JSX.Element |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Make sure you add @types/react
as a dep so that JSX
gets resolved.
|
||
// Globals | ||
export const DEFAULT_CONTEXT_KEY = '__SERVER_EFFECTS__' | ||
const contexts = [] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const contexts = [] | |
const contexts: YourContextType[] = [] |
By default, this is assumed to be never[]
, an array that will never have any elements. Mutations like push
won't work.
*/ | ||
export const createServerEffectContext = (name: string): ServerEffectContext => { | ||
console.log('--=-=-=---=-=-=-=---==--==-> createServerEffectContext') | ||
const ctxValue = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const ctxValue = { | |
const ctxValue: WhateverContextValueType = { |
Without specifying a type, requests
defaults to never[]
, which is not what we want.
AppConfig.restore = () => {} | ||
|
||
AppConfig.freeze = () => undefined |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is one noop void
, but the other undefined
?
Closing in favour of using |
Description
This PR implements the
useServerEffect
API seen in previous PR's like this one.The goal of this PR is to create a base API for use to use in building our
commerce-sdk-react
library where we'll provide react hooks for data fetching of commerce sdk data.This API can also be used on it's own as an alternative to
getProps
.TODO
useServerEffect
tofalse
.ExpressProvider
(e.g. it contains more than express values, maybe a rename is in order).useUUID
What we won't do?
Types of Changes
Changes
How to Test-Drive This PR