How to Display Object Keys and Values in a Loop in React

Intermediate8 min interview
Skills tested:
Using Object.entries() to iterate over both keys and values simultaneouslyUsing Object.keys() and Object.values() when only one dimension is neededKnowing that plain objects cannot be rendered in JSX and understanding the error React throwsUsing object keys as the key prop in map() (keys are unique by definition within an object)Handling objects whose values are themselves objects or arrays

Advertisement

🧩 Scenario

Object iteration in JSX is a common need for rendering user profiles, config summaries, API metadata, and any record-structured data. Knowing the three conversion methods (entries, keys, values) and when to use each one is a practical React skill that distinguishes candidates who understand JavaScript data structures from those who only know array-based patterns.

Architecture Walkthrough

Why Objects Cannot Be Rendered Directly

React renders only specific types: strings, numbers, booleans, null, undefined, React elements, and arrays of these. A plain JavaScript object is none of these. Attempting to embed an object in JSX ({userObject}) throws a runtime error: "Objects are not valid as a React child." You must convert the object to an array before mapping it to JSX.

JavaScript provides three static methods on Object for this: Object.keys(obj) returns an array of the object's own enumerable property names, Object.values(obj) returns an array of the values, and Object.entries(obj) returns an array of [key, value] pairs. All three produce plain arrays, which can be passed directly to map().

Choosing the Right Method

Object.entries() is the most common choice for rendering because it provides both the key and value in one destructured pair, with no need for two separate accesses. Object.keys() is appropriate when you only need to list the property names or when you need the key to look up values from a different source. Object.values() is appropriate when you need only the values (a list of prices, a set of flags) and the key names are irrelevant to the display.

Object keys are guaranteed to be unique within a single object by definition, making them safe to use as the key prop in the resulting map() call.

Handling Nested Objects

When object values are themselves objects or arrays, the render strategy depends on the depth and shape. For shallow nesting, you can render a secondary Object.entries() call inline. For deep or recursive structures, extract a recursive component or flatten the object first with a utility like Object.entries() recursion before rendering.


Key Code Explained

// Object.entries(): key and value together
interface UserProfile {
  name: string;
  email: string;
  country: string;
  plan: string;
}

function ProfileSummary({ profile }: { profile: UserProfile }) {
  return (
    <dl className="profile-grid">
      {Object.entries(profile).map(([key, value]) => (
        // Object keys are unique within an object — safe as key prop
        <div key={key} className="profile-row">
          <dt className="label">{key}</dt>
          <dd className="value">{String(value)}</dd>
        </div>
      ))}
    </dl>
  );
}


// Object.keys(): only the keys needed
interface Permissions {
  canRead: boolean;
  canWrite: boolean;
  canDelete: boolean;
  canAdmin: boolean;
}

function PermissionList({ permissions }: { permissions: Permissions }) {
  const granted = Object.keys(permissions).filter(
    (key) => permissions[key as keyof Permissions],
  );

  if (granted.length === 0) return <p>No permissions granted.</p>;

  return (
    <ul>
      {granted.map((perm) => (
        <li key={perm}>{perm}</li>
      ))}
    </ul>
  );
}


// Object.values(): only the values needed
interface PricingTier {
  monthly: number;
  yearly: number;
  lifetime: number;
}

function PriceList({ pricing }: { pricing: PricingTier }) {
  return (
    <ul>
      {Object.values(pricing).map((price, index) => (
        // Values may not be unique — index is acceptable here since the list is static
        <li key={index}>${price}</li>
      ))}
    </ul>
  );
}


// Nested object: render sub-entries inline
interface Config {
  database: { host: string; port: number };
  cache: { ttl: number; maxSize: number };
}

function ConfigViewer({ config }: { config: Config }) {
  return (
    <div>
      {Object.entries(config).map(([section, settings]) => (
        <section key={section}>
          <h3>{section}</h3>
          <ul>
            {Object.entries(settings).map(([key, value]) => (
              <li key={key}>
                <strong>{key}:</strong> {String(value)}
              </li>
            ))}
          </ul>
        </section>
      ))}
    </div>
  );
}


// WRONG: rendering an object directly in JSX
const user = { name: 'Ghazi', email: 'ghazi@example.com' };
// This throws: "Objects are not valid as a React child"
return <div>{user}</div>;

// CORRECT: convert first
return (
  <div>
    {Object.entries(user).map(([key, value]) => (
      <p key={key}>{key}: {value}</p>
    ))}
  </div>
);

In ProfileSummary, String(value) is used to safely convert any value type to a string. Without this, if a value is a boolean or number, React renders it directly (which works), but if it is an object or undefined, the render throws. Converting to string defensively handles mixed-type objects without conditional rendering for every field.


Tradeoffs

MethodReturnsUse when
Object.entries()[key, value][]Need both key and value in the render
Object.keys()string[]Need only keys, or to look up values elsewhere
Object.values()value[]Need only values, key names are irrelevant
for...in(statement)Avoid in JSX — use the above methods instead

What Interviewers Actually Check

  • Whether you know Object.entries() as the primary method for rendering key-value pairs
  • Whether you know all three conversion methods and can choose the right one
  • Whether you can explain why {userObject} throws an error in React
  • Whether you use object keys as the key prop correctly
  • Whether you can handle nested objects without deeply nesting JSX

Follow-Up Questions

  1. How does Object.entries() handle inherited properties vs for...in? Why does this matter for React rendering?
  2. How would you render a deeply nested configuration object with unknown depth using a recursive React component?
  3. How does Map differ from a plain object for React rendering, and can you use Map.entries() the same way?
  4. When would you prefer transforming an object to an array of objects before the component renders (in a selector or useMemo) vs converting inline in JSX?
  5. How does TypeScript's keyof operator help when accessing object values dynamically in a typed component?

Common Candidate Mistakes

  • Embedding an object directly in JSX and not knowing why React throws "Objects are not valid as a React child"
  • Not knowing Object.entries() and manually building two separate arrays with Object.keys() plus bracket notation
  • Using for...in inside JSX, not realizing it is a statement and cannot produce JSX output inline
  • Not knowing that for...in iterates over inherited properties while Object.entries() does not
  • Using Object.values() as the key source and getting duplicate key warnings when multiple values are the same

Interview Readiness Checklist

Before you leave this question, make sure you can answer:

  • Can you use Object.entries() to render both key and value from an object as a list?
  • Can you choose between Object.keys(), Object.values(), and Object.entries() based on what the render needs?
  • Can you explain why {userObject} throws an error in React?
  • Can you use the object key as the key prop in the map() result?
  • Can you handle a nested object with a secondary Object.entries() call inside the render?

Summary

React cannot render plain JavaScript objects. Embedding an object directly in JSX throws "Objects are not valid as a React child." To render object data, convert it to an array first using one of three static Object methods, then map the array to JSX.

Object.entries(obj) returns an array of [key, value] pairs and is the most useful for rendering key-value layouts. Object.keys(obj) returns an array of property names and is appropriate when you only need the keys or need to filter by them. Object.values(obj) returns an array of the values when the property names are irrelevant to the display. All three produce arrays that can be passed directly to map(), with object keys being unique by definition and safe to use as the key prop.

For nested objects, apply a secondary Object.entries() call inside the outer map for shallow nesting. For deeply nested or recursively structured data, extract a recursive component or flatten the structure before rendering to avoid deeply nested JSX that is difficult to read and maintain.

Frequently Asked Questions

Can I map directly over an object in JSX?

No. React cannot render plain objects. You must first convert the object to an array using Object.keys(), Object.values(), or Object.entries(), then use map() on the resulting array.

Advertisement


Stay Updated

Get the latest frontend challenges, interview questions and tutorials delivered to your inbox.

Advertisement