DEV Community

Cover image for Optimizing data flow with the keep-unchanged-values library
Constantine
Constantine

Posted on

Optimizing data flow with the keep-unchanged-values library

Hello everyone! If you're dealing with frequent data updates in your frontend development projects, especially from sources like backend servers or localStorage, this article is essential for you. Discover how the keep-unchanged-values library can enhance your React applications by optimizing data updates and minimizing performance issues. You need this if you're navigating through regular updates from various data sources.

Problem: Frequent data updates in large objects and lists cause performance issues

Solution: keep-unchanged-values combined with React.memo

How it works:

Pass two entities to the keepUnchangedValues function you want to "merge". The result is the second entity, and it will keep references to unchanged objects from the first entity:

const oldArray = [1, { a: 1 }, 3];
const newArray = [2, 3, 4, { a: 1 }];

 // result is equal to [2, 3, 4, { a: 1 }]
const result = keepUnchangedValues(oldArray, newArray);

// logs true; result[3] will be a reference to oldArray[1] since they have the same link to the object
console.log(result[3] === oldArray[1]) 
Enter fullscreen mode Exit fullscreen mode

Example:

  1. Update data from external storage periodically

  2. "Merge" new data with existing using keepUnchangedValues

  3. Update your state with "merged" data: the old nested objects will be the same, new data will be applied

import React, { useState, useEffect } from 'react';
import { keepUnchangedValues } from 'keep-unchanged-values';

const MyListComponent = () => {
  const [list, setList] = useState([]);

  useEffect(() => {
    // Fetch data from API
    const fetchHandler = () => {
      fetchData().then(newItems => {
        // Update the list with new items, maintaining unchanged ones
        const updatedList = keepUnchangedValues(list, newItems);
        // if nothing changed, returns the same list
        setList(updatedList);
      });
    }
    // Fetch initial data
    fetchHandler()
    // Set up polling
    const intervalId = setInterval(fetchHandler, 5000); // Polling every 5 seconds

    return () => clearInterval(intervalId);
  }, [list]);

  return (
    <ul>
      {list.map(item => <MemoizedListItem key={item.id} item={item} />)}
    </ul>
  );
};

const MemoizedListItem = React.memo(({ item }) => {
  // Rerenders only if the current item changes.
  // Works with shallow comparison because keepUnchangedValues maintains unchanged values
  useEffect(() => {
    somethingIneficient(item);
  }, [item]);

  return <li>{item.content}</li>;
});

export default MyListComponent;
Enter fullscreen mode Exit fullscreen mode

Benefits:

  • Unchanged list items retain their references

  • React.memo performs shallow comparisons and skips re-renders for unchanged items

Result? Smooth, efficient data updates!

Github: https://github.com/CascaSpace/keep-unchanged-values
Package: https://www.npmjs.com/package/keep-unchanged-values

More examples can be seen in the library tests https://github.com/CascaSpace/keep-unchanged-values/blob/main/src/index.test.js

If you want to learn more, check this article where we show how we optimized our Chrome Extension https://cascaspace.substack.com/p/optimizing-performance-how-our-extension

Top comments (0)