How to retrieve image data from Airtable using React?

I’m having trouble getting my React app to display images from my Airtable database. Every time I try to run the code, I get an error and can’t figure out what’s wrong.

I followed an online tutorial but changed the field names in my Airtable base to match my project. Everything should work fine but something is broken. Maybe I missed importing something important? Is there a simpler approach to fetch images from Airtable records?

Here’s my current code:

import React, { Component } from 'react';
import { Container, Row, Col, Card, CardImg, CardText, CardBody,
  CardTitle, CardSubtitle, Button } from 'reactstrap';
import './styles.css';

class MainApp extends Component {

  constructor(props) {
    super(props);
    this.state = {
      members: [],
    };
  }

  componentDidMount() {
    fetch('https://api.airtable.com/v0/appAB5JhrvUicfX2G/Team?api_key=keyF1exOkvaAnJeT9')
    .then((response) => response.json())
    .then(result => {
       console.log(result);
       this.setState({ members: result.records });
    }).catch(error => {
      // Handle error
    });
  }

  render() {
    return (
      <div className="wrapper">
        <Row>
          <Col>
            {this.state.members.map(member => <Profile {...member.fields} /> )}
          </Col>
        </Row>
      </div>
    );
  }

}

export default MainApp;

const Profile = ({ FullName, Department, LinkedIn, GitHubProfile, TwitterHandle, FacebookPage, ProfileImage }) => (
      <div className="profile-card">
        <div className="profile-body">
          <img className="profile-img" src={ProfileImage[0].url} />
          <h5 className="profile-name">{FullName}</h5>
          <p className="profile-dept">{Department}</p>
          <p className="profile-links">
            <small className="link-muted"><a href={LinkedIn}><i class="fab fa-linkedin"></i></a></small>&nbsp;
            <small className="link-muted"><a href={GitHubProfile}><i class="fab fa-github-square"></i></a></small>&nbsp;
            <small className="link-muted"><a href={TwitterHandle}><i class="fab fa-twitter-square"></i></a></small>&nbsp;
            <small className="link-muted"><a href={FacebookPage}><i class="fab fa-facebook"></i></a></small>&nbsp;
          </p>
        </div>
      </div>
);

Any help would be appreciated!

Had this exact issue last month building a team directory.

Your field names probably don’t match what’s actually in Airtable.

Go to your Airtable base and click the ProfileImage field header. Copy the exact field name - sometimes there’s hidden spaces or different capitalization you can’t see.

I always wrap image access in a conditional to avoid crashes:

{ProfileImage && ProfileImage.length > 0 && (
  <img className="profile-img" src={ProfileImage[0].url} alt={FullName} />
)}

Quick debugging tip: console.log the entire member.fields object in your map function. You’ll see exactly what field names Airtable’s returning and whether ProfileImage actually exists.

The fetch looks fine but make sure you’re using the new authorization header format if this is a recent setup.

you’re missing a null check for ProfileImage. if some records don’t have an image, ProfileImage[0].url will throw an error. try {ProfileImage && ProfileImage[0] && <img className="profile-img" src={ProfileImage[0].url} />} instead. also double-check that your airtable field is actually called “ProfileImage”.

This happens because you’re destructuring ProfileImage without checking if it exists first. When Airtable returns empty attachment fields, they come back as undefined instead of an empty array. I hit this exact issue and fixed it by adding a default value: const Profile = ({ FullName, Department, LinkedIn, GitHubProfile, TwitterHandle, FacebookPage, ProfileImage = [] }) =>. Now you can safely check ProfileImage.length > 0 before accessing the URL. Also heads up - if you’re on a newer Airtable setup, they’ve switched to bearer tokens in headers instead of query parameters.

Your API key in the URL won’t work anymore - Airtable switched to personal access tokens. You need to put it in an Authorization header instead. Use headers: { 'Authorization': 'Bearer YOUR_TOKEN' } and drop the api_key from your URL. Also throw a try-catch around that fetch since network requests fail silently sometimes. The image handling looks right if it’s an attachment field, just double-check you’re using the exact field name from your base.