How to Create a Versatile Library for Multiple Frameworks?

0

Have you ever thought about creating your own library? As a developer, building a library to solve various problems is an exciting task. Especially when aiming to create a versatile library, careful consideration is necessary. Today, let’s talk about the concept of “Framework Agnostic,” often mentioned in frontend development.

What is Framework Agnostic?

Have you heard of Framework Agnostic? This term means that the software is designed independently of a specific environment. In other words, it refers to creating a library that can be used in various environments without being tied to a specific framework.

For instance, in JavaScript libraries, a Framework Agnostic approach means writing code that is not dependent on a specific framework. This way, it can be compatible with multiple frameworks like React, Vue, etc.

Tanstack Query

A representative library is Tanstack Query. It was formerly known as React Query but has evolved into a Framework Agnostic library usable in various frameworks. How was this possible?

Looking at the source code of Tanstack Query, it is composed of a core package and adapter packages tailored to each framework. The core logic is contained in query-core, and the parts specialized for frameworks like React, Vue, Svelte, etc., are contained in their respective packages.

Let’s Build a Calculator!

Now, let’s redesign a calculator library that was strongly coupled with React so that it can be used in various frameworks.

1. Creating the Core Interface

First, define the core functions independently of the framework. Here is an example of a core class that includes the calculator’s operations logic:

class Calculator extends EventTarget {
  private _result: number = 0;
  
  get result() {
      return this._result;
  }
  
  add(a: number, b: number) {
      this._result = a + b;
      this.dispatchEvent(new Event('update'));
  }
  
  subtract(a: number, b: number) {
      this._result = a - b;
      this.dispatchEvent(new Event('update'));
  }
  
  multiply(a: number, b: number) {
      this._result = a * b;
      this.dispatchEvent(new Event('update'));
  }
  
  divide(a: number, b: number) {
      this._result = a / b;
      this.dispatchEvent(new Event('update'));
  }
}

2. Creating the React Adapter

Now, let’s integrate the core with React. Create a hook that integrates the React state and lifecycle.

import { useEffect, useState } from 'react';

function useCalculator() {
  const [result, setResult] = useState(0);
  const calculator = new Calculator();

  useEffect(() => {
    const handleUpdate = () => setResult(calculator.result);
    calculator.addEventListener('update', handleUpdate);
    
    return () => {
      calculator.removeEventListener('update', handleUpdate);
    };
  }, [calculator]);

  return {
    result,
    add: (a, b) => calculator.add(a, b),
    subtract: (a, b) => calculator.subtract(a, b),
    multiply: (a, b) => calculator.multiply(a, b),
    divide: (a, b) => calculator.divide(a, b),
  };
}

How about it? It’s easier than you thought to create a library, isn’t it?

Advantages and Disadvantages of Framework Agnostic Design

Advantages

  • Increased reusability:@b] Can be used in various frameworks.
  • Easy maintenance:@b] Separating the core and adapters makes individual modifications easier.

Disadvantages

  • Increased development and maintenance costs:@b] Need to develop and maintain adapters for each framework.
  • Increased complexity:@b] Need to manage the interface between the core and adapters.

Conclusion

Creating a Framework Agnostic library is more than just writing code that is independent of a specific environment. It involves separating the core logic from the framework-specific logic, considering maintenance and scalability. Understanding this concept through examples like Tanstack Query and applying it directly is definitely worthwhile, don’t you think?

Wouldn’t you like to create a versatile library as well? How about applying what you’ve learned today?

Leave a Reply