Skip to content

Instantly share code, notes, and snippets.

@wjramos
Last active March 14, 2023 21:14
Show Gist options
  • Save wjramos/8a9b58fae933d11b1f03a21e5b7f99a6 to your computer and use it in GitHub Desktop.
Save wjramos/8a9b58fae933d11b1f03a21e5b7f99a6 to your computer and use it in GitHub Desktop.

Global Source Providers


Table of Contents

  1. Router Context
  2. Theme Context
  3. I18next Context
  4. Relay Environment Context
  5. Snackbar Context
  6. Analytics Context
  7. Error Boundary Context

import {
  useActionData,
  useParams,
  useSearchParams,
  useNavigate,
  useRouteLoaderData,
  useNavigation,
  useMatches,
  useMatch,
  useLocation,
  useInRouterContext,
  RouterProvider, 
  createBrowserRouter,
  createRoutesFromElements,
} from 'react-router-dom'

const actionData = useActionData()
const loaderData = useRouteLoaderData(routeId)
const nearestLoaderData = useLoaderData()
const params = useParams()
const searchParams = useSearchParams()
const navigate = useNavigate()
const outletContextValue = useOutletContext()
const location = useLocation()
const navigationState = useNavigation()
const breadcrumbs = useMatches()
const matchedRoute = useMatch()
const isInRouterContext = useInRouterContext()

if (isInRouterContext)
  return (
    <Routes>
      {/* ... */}
    </Routes>
  )

// DEV
return (
  <RouterProvider router={createBrowserRouter(createRoutesFromElements(<Route>{/* ... */}</Route>))} />
)
  • Any Components and Hooks that do not initiate data-loading (any configured data-loading is available)
  • IMPORTANT: Cannot nest RouterProvider

  • useTheme - Returns parent theme, which is extendable within a nested ThemeProvider

    import { createTheme, useTheme, ThemeProvider } from '@mui/material'
    
    return (
      <ThemeProvider theme={createTheme(useTheme(), CUSTOM_THEME_OPTIONS)}>
        {/* ... */}
      </ThemeProvider>
    )
  • useMediaQuery - Returns true if a media query is applied

    import { useTheme, useMediaQuery } from '@mui/material'
    
    const theme = useTheme()
    
    useMediaQuery(theme.breakpoints.up('sm'))
    // OR
    useMediaQuery((theme) => theme.breakpoints.up('sm'))

  • useTranslation - returns t translation function and i18n i18next instance
      import { useTranslation } from 'react-i18next'
    
      const { t, i18n } = useTranslation()
    
      // Display translated string
      // Option 1
      t('translation.key', 'English Message', { ...options })
    
      // Option 2
      return (
        <Trans t={t} i18nKey="translation.key" {...options}>
          English Message
        </Trans>
      )
    
      // Change language
      i18n.changeLanguage('fr-ca')
    
      // Access language
      const currentLanguage = i18n.language
    
      // Load translations
      i18n.on('languageChanged', (language) => {
        if (!i18n.hasResourceBundle(language, namespace)) 
          fetch(`${moduleBasePath}/translations/${language}.json`)
            // eslint-disable-next-line promise/prefer-await-to-then -- ignored for now
            .then((resp) => resp.json())
            // eslint-disable-next-line promise/prefer-await-to-then -- ignored for now
            .then((resources) => i18n.addResourceBundle(language, namespace, resources, true, true))
            .catch((error) => {
              // eslint-disable-next-line no-console -- console.log needed
              console.error(`Error loading translations for language: ${language}`, error)
            })
      })

  • useRelayEnvironment
    import { RelayEnvironmentProvider } from 'relay-hooks'
    
    const relayEnvironment = useRelayEnvironment()
    
    return (
      <RelayEnvironmentProvider environment={relayEnvironment}>
        {/* ... */}
      </RelayEnvironmentProvider>
    )

  • useSnackbar - returns enqueueSnackbar and closeSnackbar
    import { SnackbarProvider, useSnackbar } from 'notistack'
    
    return (
      <SnackbarProvider maxSnack={3}>
        {/* ... */}
      </SnackbarProvider>
    )
    
    const { enqueueSnackbar, closeSnackbar } = useSnackbar()
    
    const key = enqueueSnackbar(message, { ...options })
    
    closeSnackbar(key)

AnalyticsProvider

TBD


ErrorBoundary

Nestable, you should use your own.

  import { useErrorHandler, ErrorBoundary } from 'react-error-boundary'

  return (
    <ErrorBoundary 
      FallbackComponent={Component} 
      fallback={<Component />} 
      fallbackRender={() => <Component />} 
      onError={() => undefined} 
      onReset={() => undefined}
      resetKeys={[/* ... */]} 
      onResetKeysChange={() => undefined}
    >
      {/* ... */}
    </ErrorBoundary>
  )

  const handleError = useErrorHandler();

  handleError(new Error(/* ... */))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment