Skip to content

Instantly share code, notes, and snippets.

@JamieMason
Forked from adamkl/AppContextProvider.tsx
Created February 10, 2020 22:40
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save JamieMason/9d1b757b082d4b5e608787648a15bb7b to your computer and use it in GitHub Desktop.
Save JamieMason/9d1b757b082d4b5e608787648a15bb7b to your computer and use it in GitHub Desktop.
xState service layer
import React from "react";
import { createUserSessionService } from "services/UserSessionService";
import { createNavService } from "services/NavService";
// Wiring up our "IOC container"
const userSessionService = createUserSessionService();
// NavService depends on UserSessionService
const navService = createNavService(userSessionService);
const dependencies = {
userSessionService,
navService
};
const AppContext = React.createContext(dependencies);
const AppContextProvider: React.FC = props => {
return (
<AppContext.Provider value={dependencies}>
{props.children}
</AppContext.Provider>
);
};
export { AppContext, AppContextProvider };
import React from "react";
import ReactDOM from "react-dom";
import App from "App";
import { AppContextProvider } from "AppContextProvider";
// Wrapping our app in our "IOC container"
ReactDOM.render(
<AppContextProvider>
<App />
</AppContextProvider>,
document.getElementById("root")
);
import React from "react";
import { useHistory } from "react-router-dom";
import { SideNav } from "SideNav";
import { useNavService } from "services/NavService";
const Navbar: React.FC = () => {
const [navState] = useNavService(); // Inject dependency
// Links automatically change based on authentication state
// from UserSessionService
const { links } = navState.context;
return (
<>
<SideNav
menuItems={links}
menuHeaderLink="/"
menuHeaderLinkAlt="Home"
/>
</>
);
};
export default Navbar;
import { useContext } from "react";
import { Machine, interpret, Interpreter } from "xstate";
import { useService } from "@xstate/react";
import { AppContext } from "AppContextProvider";
import { config, NavContext, NavEvent, NavStateSchema} from "./machine";
import { UserSessionService } from "services/UserSessionService";
// Custom hook for "dependency injection"
export const useNavService = () => {
const { navService } = useContext(AppContext);
return useService(navService);
};
export const createNavService = (userSessionService: UserSessionService): NavService => {
const navMachine = Machine<NavContext, NavStateSchema, NavEvent>(config);
const navService = interpret(navMachine).start();
// wire up state transition dependency between
// NavService and UserSessionService
userSessionService.onTransition(state => {
if (state.matches("AUTHENTICATED")) {
navService.send("SWITCH_TO_AUTHENTICATED_LINKS");
} else {
navService.send("SWITCH_TO_UNAUTHENTICATED_LINKS");
}
});
return navService;
};
import { useContext } from "react";
import { Machine, interpret, Interpreter } from "xstate";
import { useService } from "@xstate/react";
import { AppContext } from "AppContextProvider";
import { config, UserSessionContext, UserSessionStateSchema, UserSessionEvent } from "./machine";
// Custom hook for "dependency injection"
export const useUserSessionService = () => {
const { userSessionService } = useContext(AppContext);
return useService(userSessionService);
};
export const createUserSessionService = (): UserSessionService => {
const userSessionMachine = Machine<UserSessionContext, UserSessionStateSchema, UserSessionEvent>(config);
return (
interpret(userSessionMachine)
.start()
);
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment