Skip to content

Instantly share code, notes, and snippets.

@jimkeller
Last active September 29, 2022 02:03
Show Gist options
  • Save jimkeller/8f338c91d9772fe1c932e597dcad2eb2 to your computer and use it in GitHub Desktop.
Save jimkeller/8f338c91d9772fe1c932e597dcad2eb2 to your computer and use it in GitHub Desktop.
Example of dependency injection in React using Context
/**
*
* This file creates a React Context to hold the functionality for connecting to the
* employee data endpoint.
*
* I'm using Context here to mimic dependency injection so that the
* client can be more easily mocked for testing, or swapped out in the future.
*
* You can import EmployeeDataProvider from this file then
* wrapping a child component in <EmployeeDataProvider></EmployeeDataProvider> to give the component
* access to the data provider.
*
*/
import React from "react";
import { createContext, useContext } from "react";
import PropTypes from 'prop-types';
import axios from "axios";
import regeneratorRuntime from "regenerator-runtime"; // eslint-disable-line no-unused-vars
/*
* Create the context
*/
const EmployeeDataClientContext = createContext(undefined);
/**
*
* This hook function is basically just a helper so that components themselves don't have
* to use createContext(). Instead we can provide this hook and do some error checking here.
*/
export const useEmployeeDataClient = () => {
const context = useContext(EmployeeDataClientContext);
if (context == 'undefined') {
throw new Error('EmployeeClientContext was not provided. Make sure your component is a child of the EmployeeClient');
}
return context;
}
/**
* The actual provider for the context, with the service within it.
*/
const EmployeeDataProvider = ({children}) => {
const endpoint_base_url = "http://localhost:3035/employees/"
/* Set up our service within this provider */
const employee_data_client_service = {
async getResults(id) {
const response = await axios.get(`${endpoint_base_url}/${id}`)
.catch((err) => {
throw new Error("Error fetching results.");
});
if (response.data.results) {
return response.data.results;
}
}
}
/**
* Set up an EmployeeDataClient provider component for this context.
* This essentially allows us to provide employee data fetching functionality
* to other components as if it were an injected service.
*/
return(
<>
<EmployeeDataClientContext.Provider value={employee_data_client_service}>
{children}
</EmployeeDataClientContext.Provider>
</>
)
}
EmployeeDataProvider.propTypes = {
children: PropTypes.node
}
export default EmployeeDataProvider;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment