Skip to main content

Basic Usage with React

work in progress

Fetching sync and async dependencies from ITI in React is conceptually similar to data fetching. If you've used libraries like React Query, swr, Apollo Client or similar this will feel familiar.

Data fetching

./src/Profile.tsx
import useSWR from "swr"

function Profile() {
const { data, error } = useSWR("/api/user", fetcher)

if (error) return <div>failed to load</div>
if (!data) return <div>loading...</div>
return <div>hello {data.name}!</div>
}

Async Request for single item in ITI

./src/Profile.tsx
import { useContainer } from "./_containers/main-app"

function Profile() {
const [auth, authErr] = useContainer().auth

if (authErr) return <div>failed to load</div>
if (!auth) return <div>loading...</div>

return <div>hello {auth.profile.name}!</div>
}

Async Request for multiple items

useContainerSet

./src/Profile.tsx
import { useContainer, useContainerSet } from "./_containers/main-app"

// Callback style

function Profile() {
const [profileDeps, profileDepsErr] = useContainerSet((c) => [c.auth, c.env])

if (!profileDeps || profileDepsErr) return null
const { auth, env } = profileDeps

return <div>hello {auth.profile.name}!</div>
}

// Literal style
function Profile() {
const [profileDeps, profileDepsErr] = useContainerSet(["auth", "env"])

if (!profileDeps || profileDepsErr) return null
const { auth, env } = profileDeps

return <div>hello {auth.profile.name}!</div>
}

Ensure Sync Containers

You might want a simpler API for your components

So we could go

From:

const [profileDeps, profileDepsErr] = useContainerSet(["auth", "env"])
if (!profileDeps || profileDepsErr) return null

To:

const { auth, env } = useProfileDeps()

To achieve that we will have to create a wrapping component. Very similar to React.Suspense

// This component is loaded dynamically
const OtherComponent = React.lazy(() => import("./OtherComponent"))

function MyComponent() {
return (
// Displays <Spinner> until OtherComponent loads
<React.Suspense fallback={<Spinner />}>
<div>
<OtherComponent />
</div>
</React.Suspense>
)
}

We will create a wrapping component that will fetch dependencies, provide fallback and provide context for nested components

./src/_containers-react/EnsureEcommerce.tsx
import React, { useContext } from "react"
import { generateEnsureContainerSet } from "iti-react"
import { useContainerSet } from "./_editor-app-hooks"

const x = generateEnsureContainerSet(() =>
useContainerSet(["ecommerce", "auth"])
)
export const EnsureEcommerceContainer = x.EnsureWrapper
export const useEcommerceContext = x.contextHook
./src/App.tsx
import { EnsureEcommerceContainer } from "./_containers-react/EnsureEcommerce"

export const App = () => (
<div className="App">
<EnsureEcommerceContainer fallback={<>Loading</>}>
<MainApp />
</EnsureEcommerceContainer>
</div>
)
./src/Currency.tsx
import { useEcommerceContext } from "../../../../_containers-react/EnsureEcommerce"

export const CurrencyInfo = () => {
const { currencyStore, taxStore } = useEcommerceContext().ecommerce

return <div>{currencyStore.currency}</div>
}