Skip to main content

React context

Description​

Create a react context that holds the dependency.

The context can have a default value, or it can be set via a provider in the production application.

Access the dependency via useContext.

The context can live with either the dependent code, or the dependency.

If you choose to locate the context with the dependency, you may wish to export a named wrapper that invokes useContext.

In tests, use setContext or withContext to set the value of the context to the test implementation.

Notes​

This is a react-specific technique.

Example​

api.js

import { createContext, useContext } from 'react'

// production api implementation
export const api = {
getWidget: (id) => { ... }
}

export const ApiContext = createContext(api)

// This hook is used anywhere api is needed
export const useApi = () => useContext(ApiContext)

WidgetName.jsx

import { useApi } from './api'
import React, { useEffect, useState } from 'react'

const WidgetName = ({
id
}) => {
const api = useApi()

const [name, setName] = useState('')

useEffect(() => {
api.getWidget(id).then(widget => setName(widget ? widget.name: 'Unkonwn Widget'))
}, [id])

return <span>{name}</span>
}

WidgetName.test.jsx

import { isolateComponent } from 'isolate-react'
import { ApiContext } from './api'
import { widgets } from './widgets'

describe("WidgetName", () => {
test("unknown widget returns 'Unknown Widget'", async () => {
const fakeApi = {
getWidget: async () => undefined
}

const isolateWithFakeApi = isolateComponent.withContext(ApiContext, fakeApi)

const widgetComponent = isolateWithFakeApi(<WidgetName widgetApi={fakeApi} widgetId={42} />)

// Wait for the api promise and update the component
await widgetComponent.waitForRender()

expect(widgetComponent.findOne('span').content()).toEqual('Unknown Widget')
})
})