Dependency Inversion Principle in React

Let's consider the following concept: You are utilizing a function to retrieve users from an API. From a JavaScript perspective, it would appear as follows

const response = await fetch('some url');

However, this approach has a drawback. It lacks flexibility if you need to change the execution "environment" of this component. For instance, you may want to execute it for testing purposes. In such cases, relying on the API to function correctly is not ideal since you only want to test the component itself. To address this, we should separate this component from direct dependency on the API. This way, we can provide fake data for testing and ensure that the data source is not causing any issues with our component. A more recommended approach involves creating an abstract entity, such as a class or function, and allowing instantiated implementations to be passed in. Let's see how this would work for a React function component.

Let's suppose we are developing a component that lists users. Here's an example of how it could be implemented:

// let's assume this is a server side component just for simplification

// NOT USING DEPENDENCY INVERSION
async function UsersList() {
	const users = await fetch("some-url/users")
}


// USING DEPENDENCY INVERSION
async function UsersList({ getUsers }) {
	const users = await getUsers()
}

// Test environment
<UsersList getUsers={() => [{ id: 0, name: "Vinicius" }, { id: 1, name: "John" }]}/>

// Production environment
<UsersList getUsers={() => await fetch("some-url/users")}/>

Notice how, by applying the Dependency Inversion Principle, we can execute a function that returns static data, which is perfect for testing purposes. The same function used in the first example is now suitable for production as well. As demonstrated, the DIP is an effective way to decouple functionalities. Although initially conceived for Object-Oriented Programming languages, it is also applicable to functional programming languages. The key concept is injecting an already instantiated implementation derived from an abstract entity, allowing control over the function's behaviour based on the execution environment.

SOLIDJAVASCRIPTREACTPATTERNS
Avatar for Vinicius Ribeiro

Written by Vinicius Ribeiro

Web/mobile developer using React

Loading

Fetching comments

Hey! 👋

Got something to say?

or to leave a comment.