AN.
  • Home
  • Experience
  • Projects
  • Blog
AN.

Built with Next.js, Tailwind v4, and Framer Motion.

GitHubLinkedInNPM
© 2026 Ahmed Nasser. All rights reserved.
Back to writing
January 15, 2024•
5 min read

Clean Your Objects Efficiently in JavaScript

#JavaScript#React#Lodash#Clean Code#Web Development
A
Ahmed NasserSenior Software Engineer

Dealing with APIs often requires sending clean data objects—free from null, undefined, or empty strings. Instead of manually checking every property, you can automate this process with a recursive "clean" function.

In this guide, we'll build a robust utility to sanitize your JavaScript objects, ensuring your API payloads are always lean and valid.


Why Clean Your Objects?

  • API Compatibility: Many backends (especially those using GraphQL or strict TypeScript schemas) might throw errors if they receive unexpected null values.
  • Bandwidth Efficiency: Removing unnecessary properties reduces the size of your network requests.
  • Data Integrity: Ensures that your application state only contains meaningful information.

The Recursive Solution

This function deep-cleans an object by traversing all levels of nesting, including arrays.

1. Install Dependencies

While you can do this with vanilla JS, Lodash provides excellent deep cloning and object manipulation utilities that handle edge cases (like circular references) more gracefully.

npm install lodash

2. Implementation

import _ from "lodash";
 
/**
 * Recursively removes null, undefined, and empty string values from an object.
 * Also handles empty objects and arrays resulting from the cleaning process.
 */
export const cleanObject = (obj) => {
  // Create a deep copy to maintain immutability
  const copy = _.cloneDeep(obj);
 
  const clean = (data) => {
    // Return primitive values as-is
    if (typeof data !== "object" || data === null) {
      return data;
    }
 
    // Handle Arrays
    if (Array.isArray(data)) {
      return data
        .map((item) => clean(item))
        .filter((item) => item !== null && item !== undefined && item !== "");
    }
 
    // Handle Objects
    const newObj = {};
    for (const key in data) {
      if (Object.prototype.hasOwnProperty.call(data, key)) {
        const value = data[key];
 
        // Skip null, undefined, or empty strings
        if (value === null || value === undefined || value === "") {
          continue;
        }
 
        const cleanedValue = clean(value);
 
        // Skip empty arrays or empty objects created by the cleaning process
        if (Array.isArray(cleanedValue) && cleanedValue.length === 0) continue;
        if (
          typeof cleanedValue === "object" &&
          cleanedValue !== null &&
          Object.keys(cleanedValue).length === 0
        ) {
          continue;
        }
 
        newObj[key] = cleanedValue;
      }
    }
    return newObj;
  };
 
  return clean(copy);
};

Practical Example

Let's see how it handles a complex, "dirty" object:

const dirtyObject = {
  name: "John Doe",
  email: "", // Should be removed
  age: 30,
  preferences: null, // Should be removed
  address: {
    street: "123 Main St",
    city: "", // Should be removed
    details: {
      apt: null, // Should be removed
    },
  },
  tags: ["react", null, "javascript", ""], // Should clean array
};
 
const cleanData = cleanObject(dirtyObject);
 
/* 
Result:
{
  name: "John Doe",
  age: 30,
  address: {
    street: "123 Main St"
  },
  tags: ["react", "javascript"]
}
*/

Vanilla JavaScript Alternative (No Lodash)

If you prefer not to use external libraries, here is a lightweight version for modern browsers:

export const cleanObjectVanilla = (obj) => {
  return Object.fromEntries(
    Object.entries(obj)
      .filter(([_, v]) => v != null && v !== "")
      .map(([k, v]) => [
        k, 
        v === Object(v) && !Array.isArray(v) ? cleanObjectVanilla(v) : v 
      ])
      .filter(([_, v]) => 
        v !== null && 
        (typeof v !== "object" || Object.keys(v).length > 0)
      )
  );
};

Key Considerations

  1. Immutability: Always clone your data before cleaning if it's part of a React state or Redux store.
  2. Date Objects: Be careful with Date objects, as typeof date === 'object'. You might need to add a check for data instanceof Date.
  3. Performance: For extremely large objects (thousands of nested keys), recursive operations can be expensive. Consider cleaning only the specific fields you need.

Conclusion

Cleaning your data objects is a small step that leads to much more reliable and maintainable code. Whether you use the Lodash version for maximum robustness or the Vanilla JS version for zero dependencies, your APIs will thank you!

4. Usage Example

Integrate the clean function into your React application:

// App.js
import { cleanObject } from "./cleanObject";
import { dirtyObject } from "./dummyData";
import "./styles.css";
 
export default function App() {
  console.log("dirty", dirtyObject);
  const cleanedObject = cleanObject(dirtyObject);
  console.log("cleanedObject", cleanedObject);
 
  return (
    <div className="App">
      <h1>Object Cleaning Demo</h1>
      <div>
        <h2>Original Object</h2>
        <pre>{JSON.stringify(dirtyObject, null, 2)}</pre>
      </div>
      <div style={{ marginTop: "50px" }}>
        <h2>Cleaned Object</h2>
        <pre>{JSON.stringify(cleanedObject, null, 2)}</pre>
      </div>
    </div>
  );
}

5. The Result

After cleaning, your object will look like this:

{
  "name": "John Doe",
  "age": 30,
  "address": {
    "street": "123 Main St"
  },
  "hobbies": [
    "coding",
    "reading",
    {
      "age": 333,
      "hobbies": ["2", 3]
    }
  ]
}

Conclusion

By following these steps, you can ensure your objects are cleaned of null, undefined, and empty values before sending them to your backend. This approach:

  • Maintains immutability by cloning the original object
  • Handles nested structures through recursion
  • Filters arrays to remove invalid values
  • Removes empty objects and arrays automatically

This pattern is especially useful when working with forms, API requests, and data validation in modern JavaScript applications.

Share on TwitterShare on LinkedIn
A

Written by Ahmed Nasser

Senior Frontend Engineer

Passionate about building exceptional digital experiences. Specialized in React, Next.js, and modern web architectures. I love sharing my knowledge through technical writing and open-source contributions.

Social
TwitterLinkedInGitHub

Share

Share on TwitterShare on LinkedIn

Continue Reading

More articles you might find interesting

View all articles
Feb 10, 2024
3 min

How To Make Recursion: Use Case For new Map Syntax

Learn how to implement recursion in React components to manage nested radio button groups using JavaScript's Map object for efficient state management.

#React#JavaScript
Jan 4, 2026
3 min

Why Your React State is "One Step Behind" 🐢

Have you ever tried to log or send state immediately after calling its set function, only to find the old value instead? This is one of the most common "aha!" moments for React developers.

#React#JavaScript
Mar 5, 2024
5 min

Why You Should Not Use Index as Key in React Lists

Discover why using array indices as keys in React can lead to performance issues and bugs, and learn the best practices for proper list rendering.

#React#Next.js