How to Conditionally Render UI in React from API Data

Conditional Rendering Based on API Response in React

Conditional Rendering Based on API Response in React

Learn how to conditionally render a premium badge in React components based on user data fetched from an API.

🎯 Scenario

You fetch user data from an API. Each user object includes a property such as isPremium. You want to show a “Premium Badge” only for users who have isPremium: true.

❓ Problem Explanation

In React, when you fetch data asynchronously, you must wait for the data to load before using it in your JSX. Directly accessing nested properties before the data arrives can lead to errors. Hence, conditional rendering is required to safely show or hide elements like a premium badge.

⚠️ Common Pitfalls

  • Accessing user.isPremium before data is loaded (null or undefined errors)
  • No loading state — causes flash of empty content
  • Improper use of conditional rendering (e.g., not using checks)

✅ Step-by-Step Implementation

Let’s break down how to fetch user data and conditionally render a premium badge based on the API response in a React functional component.


    // Step 1: Import hooks from React
    import React, { useEffect, useState } from "react";
    
    // Step 2: Define the functional component
    const UserProfile = () => {
      // Step 3: Create two state variables
      // `user` to hold fetched user data, `loading` to control loading UI
      const [user, setUser] = useState(null);
      const [loading, setLoading] = useState(true);
    
      // Step 4: Use useEffect to fetch data after component mounts
      useEffect(() => {
        fetchUserData();  // Call our async function on load
      }, []);
    
      // Step 5: Define the async function to fetch user data from an API
      const fetchUserData = async () => {
        try {
          const response = await fetch("https://api.example.com/user/1");
          const data = await response.json();
          setUser(data);  // Set the fetched data into `user`
        } catch (error) {
          console.error("Error fetching user:", error);
        } finally {
          setLoading(false);  // Mark loading as done, even if there was an error
        }
      };
    
      // Step 6: Conditional UI if data is still loading
      if (loading) return <p>Loading user...</p>;
    
      // Step 7: Render the actual user UI based on the data
      return (
        <div className="user-profile">
          <h2>{user.name}</h2>
    
          // Step 8: Conditionally render the premium badge
          {user.isPremium && (
            <span className="premium-badge">🌟 Premium User</span>
          )}
    
          // Step 9: Conditionally render a free plan badge for non-premium users
          {!user.isPremium && (
            <span className="free-badge">Free Plan User</span>
          )}
        </div>
      );
    };
    
    // Step 10: Export the component so it can be used elsewhere
    export default UserProfile;
      

🔍 This implementation covers data fetching, loading state handling, and conditional rendering in a clean and reusable format. It follows React best practices using useEffect for lifecycle management and useState for dynamic UI updates.

🧪 Example Output

For Premium User: “🌟 Premium User” is shown.

For Free User: “Free Plan User” is shown instead.

🧠 Key Concepts Covered

  • useEffect – fetch API data after component mounts
  • useState – store user data and loading status
  • Conditional JSX – use logical && or ternaries
  • Fallback UI – handle loading states

✅ Best Practices

  • Use loading state to prevent UI flickering
  • Always check if user exists before accessing properties
  • Keep conditionals clean and readable
  • Extract repeated UI logic into reusable components

📤 Bonus: Reusable PremiumBadge Component


const PremiumBadge = ({ isPremium }) => {
  if (!isPremium) return null;

  return (
    <span className="premium-badge">
      🌟 Premium User
    </span>
  );
};
      

<PremiumBadge isPremium={user.isPremium} />

🧩 Real-World Use Case

In an e-commerce app, premium customers may get exclusive deals. A badge helps visually differentiate them across orders, profile pages, or support panels.

🎤 Interview Questions and Answers

1. What is conditional rendering in React?

Answer: Conditional rendering in React means showing or hiding elements based on logical conditions. This allows dynamic user interfaces where certain parts of the component are displayed based on state, props, or fetched data.

Example:


    {user.isPremium && <span>🌟 Premium User</span>}
        

2. What are the different ways to implement conditional rendering?

Answer: You can use several techniques in React for conditional rendering:

  • Short-circuiting: {condition && <Component />}
  • Ternary operator: {condition ? <A /> : <B />}
  • Conditional statements: Use if inside functions before returning JSX.
  • Logical OR fallback: {value || "Default"}

    // Example:
    return (
      <div>
        {isLoggedIn ? <Dashboard /> : <LoginForm />}
      </div>
    );
        

3. How do you safely access data from an API response to avoid runtime errors?

Answer: You must check if the data exists before using its properties. You can use optional chaining (?.), loading state, or fallback conditions.


    // Safe approach:
    if (!user) return <p>Loading...</p>;
    
    return <p>Hello {user?.name}</p>;
        

4. How can you improve performance when rendering a list of conditionally rendered components?

Answer: Use React.memo to prevent re-renders of unchanged components, and always use unique key props in lists.


    const UserCard = React.memo(({ user }) => (
      <div>
        <h4>{user.name}</h4>
        {user.isPremium && <span>🌟 Premium</span>}
      </div>
    ));
        

5. Why is it a good practice to separate conditional rendering into small components?

Answer: Breaking logic into smaller components improves readability, reusability, and testing. It also makes it easier to apply unit tests and isolate logic.


    // Separate reusable badge
    const PremiumBadge = ({ isPremium }) => {
      return isPremium ? <span>🌟 Premium User</span> : null;
    };
        

6. What is the best way to handle loading and error states in data-driven React components?

Answer: Always define a loading and error state when fetching data, and use them to render fallback UI.


    if (loading) return <p>Loading...</p>;
    if (error) return <p>Something went wrong.</p>;
    
    return <UserProfile />;
        

⚡ Performance Optimization Tips

When working with conditional rendering and API responses in React, especially in components that re-render frequently or render large lists (like users or items), it’s essential to optimize performance. Here are best practices and techniques:

1. Use React.memo for Pure Functional Components

What it does: Prevents re-rendering unless props change.


    const UserCard = React.memo(({ user }) => (
      <div className="user-card">
        <h3>{user.name}</h3>
        {user.isPremium && <PremiumBadge />}
      </div>
    ));
        

Use it when: The component’s output depends only on props and doesn’t change unless props change.

2. Avoid Unnecessary State Updates

Why: Updating state when not needed triggers re-renders.


    // ❌ Avoid this:
    setUser({ ...user }); // causes re-render even if no data changed
    
    // ✅ Instead:
    if (JSON.stringify(newData) !== JSON.stringify(user)) {
      setUser(newData);
    }
        

Only update state if data has actually changed.

3. Use Key Props Properly in Lists

Why: Helps React efficiently re-render list items.


    {users.map(user => (
      <UserCard key={user.id} user={user} />
    ))}
        

Never use array index as key if the list may change.

4. Lazy Load Components (Code Splitting)

What: Load large or optional components only when needed.


    import React, { Suspense, lazy } from "react";
    
    const PremiumBadge = lazy(() => import("./PremiumBadge"));
    
    return (
      <Suspense fallback={<span>Loading...</span>}>
        {user.isPremium && <PremiumBadge />}
      </Suspense>
    );
        

5. Avoid Inline Functions in JSX (when used frequently)

Why: Inline functions re-create on every render, reducing memoization efficiency.


    // ❌ Avoid
    <button onClick={() => handleClick(user.id)}>Click</button>
    
    // ✅ Instead
    const handleClick = useCallback((id) => {
      // logic
    }, []);
    
    <button onClick={() => handleClick(user.id)}>Click</button>
        

Tip: Use useCallback to memoize functions.

6. Memoize Expensive Derived Values with useMemo

Calculate derived values only when dependencies change.


    const filteredUsers = useMemo(() => {
      return users.filter(user => user.isPremium);
    }, [users]);
        

7. Use a Loading Skeleton or Placeholder

Improve perceived performance by rendering placeholders while data loads.


    {loading ? <SkeletonUserCard /> : <UserCard user={user} />}
        

Learn more about React setup

6 thoughts on “How to Conditionally Render UI in React from API Data”

  1. Wow, wonderful blog layout! How long have you been blogging for? you make blogging look easy. The overall look of your site is fantastic, let alone the content!

Comments are closed.

Scroll to Top