-
Notifications
You must be signed in to change notification settings - Fork 894
refactor: Refactor auth provider #5782
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
Changes from 1 commit
244845f
b83f9c2
528892f
9f0e0ee
1714ca5
884dac7
970e1a5
6e572e3
6442b3a
5747590
7768e95
1173d16
ea4300b
d8826c3
e12f437
9e7a875
3e589f1
dce50e3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
import { useMachine } from "@xstate/react" | ||
import { | ||
AppearanceConfig, | ||
BuildInfoResponse, | ||
Entitlements, | ||
} from "api/typesGenerated" | ||
import { FullScreenLoader } from "components/Loader/FullScreenLoader" | ||
import { createContext, FC, PropsWithChildren, useContext } from "react" | ||
import { appearanceMachine } from "xServices/appearance/appearanceXService" | ||
import { buildInfoMachine } from "xServices/buildInfo/buildInfoXService" | ||
import { entitlementsMachine } from "xServices/entitlements/entitlementsXService" | ||
|
||
interface Appearance { | ||
config: AppearanceConfig | ||
preview: boolean | ||
setPreview: (config: AppearanceConfig) => void | ||
save: (config: AppearanceConfig) => void | ||
} | ||
|
||
interface DashboardProviderValue { | ||
buildInfo: BuildInfoResponse | ||
entitlements: Entitlements | ||
appearance: Appearance | ||
} | ||
|
||
export const DashboardProviderContext = createContext< | ||
DashboardProviderValue | undefined | ||
>(undefined) | ||
|
||
export const DashboardProvider: FC<PropsWithChildren> = ({ children }) => { | ||
const [buildInfoState] = useMachine(buildInfoMachine) | ||
const [entitlementsState] = useMachine(entitlementsMachine) | ||
const [appearanceState, appearanceSend] = useMachine(appearanceMachine) | ||
const { buildInfo } = buildInfoState.context | ||
const { entitlements } = entitlementsState.context | ||
const { appearance, preview } = appearanceState.context | ||
const isLoading = !buildInfo || !entitlements || !appearance | ||
|
||
const setAppearancePreview = (config: AppearanceConfig) => { | ||
appearanceSend({ | ||
type: "SET_PREVIEW_APPEARANCE", | ||
appearance: config, | ||
}) | ||
} | ||
|
||
const saveAppearance = (config: AppearanceConfig) => { | ||
appearanceSend({ | ||
type: "SAVE_APPEARANCE", | ||
appearance: config, | ||
}) | ||
} | ||
|
||
if (isLoading) { | ||
return <FullScreenLoader /> | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What do you think about keeping this context 'pure' meaning it doesn't really dictate UI at all? Then we could expose There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not sure if I got it. I don't see too much value on having it pure since the value, from what I see, is to have a provider that handle that in one single place but maybe I'm missing something. I based this provider on https://kentcdodds.com/blog/authentication-in-react-applications There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think in that example, he's showcasing functionality instead of organization, but I'm happy to talk it through in Discord. It's also not a blocker. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Interesting. I'm usually agnostic about where to put these, but I don't know if I've ever seen a provider render a spinner. But I see that Kent really does it intentionally:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm, I could see that. I was looking at his comment below:
So I figured the component is the consumer of the context, and it should have something like this:
I guess this is an argument for colocation, kind of similar to what we were discussing with long files. But just because it isn't a pattern I've seen before doesn't mean it's wrong! I'm happy to keep the loaders in the context. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I agree 100%. In this case, I just think would be too much to have another component to handle the spinner. If at some point it starts to do more and more stuff, I think would make sense to split it. |
||
|
||
return ( | ||
<DashboardProviderContext.Provider | ||
value={{ | ||
buildInfo, | ||
entitlements, | ||
appearance: { | ||
preview, | ||
config: appearance, | ||
setPreview: setAppearancePreview, | ||
save: saveAppearance, | ||
}, | ||
}} | ||
> | ||
{children} | ||
</DashboardProviderContext.Provider> | ||
) | ||
} | ||
|
||
export const useDashboard = (): DashboardProviderValue => { | ||
const context = useContext(DashboardProviderContext) | ||
|
||
if (!context) { | ||
throw new Error("useDashboard only can be used inside of DashboardProvider") | ||
} | ||
|
||
return context | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,8 @@ | ||
import { useSelector } from "@xstate/react" | ||
import { FeatureName } from "api/typesGenerated" | ||
import { useContext } from "react" | ||
import { useDashboard } from "components/Dashboard/DashboardProvider" | ||
import { selectFeatureVisibility } from "xServices/entitlements/entitlementsSelectors" | ||
import { XServiceContext } from "xServices/StateContext" | ||
|
||
export const useFeatureVisibility = (): Record<FeatureName, boolean> => { | ||
const xServices = useContext(XServiceContext) | ||
return useSelector(xServices.entitlementsXService, selectFeatureVisibility) | ||
const { entitlements } = useDashboard() | ||
return selectFeatureVisibility(entitlements) | ||
} |
Uh oh!
There was an error while loading. Please reload this page.