0

I am trying to connect to the USDA Food Central database using an API.

let uri = encodeURI(`https://api.nal.usda.gov/fdc/v1/foods/search?api_key=${MY_API_KEY}&query=${search}`)

I want to use the API to map certain fields.

class AddFoodItemList extends Component {
  static contextType = AddFoodContext;
  render() {
    const listItems = this.context.FoodSearch.map((foods) =>
      <FoodItem
        key={foods.brandOwner}
        brandOwner={foods.brandOwner}
        fdcId={foods.fdcId}
      />
    );

    return (
      <div id="AddFoodItemList">
        {listItems}
      </div>
    );
  }

}

export default AddFoodItemList;

The returned JSON is this screenshot attached: Returned JSON

I am getting an error, TypeError: Cannot read property 'map' of undefined. Why do you think this is the case? Any sort of help or suggestions are appreciated!

Linda Paiste
  • 38,446
  • 6
  • 64
  • 102
  • This means that your context does not have a property `FoodSearch` or the property `FoodSearch` has the value `undefined`. I cannot debug this without seeing how you are passing a value to the context provider. – Linda Paiste Apr 05 '21 at 02:50
  • Does this answer your question? [Cannot read property 'map' of undefined](https://stackoverflow.com/questions/24706267/cannot-read-property-map-of-undefined) – Bishan Apr 05 '21 at 03:03

1 Answers1

0

You are attempting to access a property FoodSearch on the value of your AddFoodContext provider. The error tells you that this property is undefined. If the object in your screenshot is the value of your context then you want to access the property foods instead. This is an array whose elements are objects with properties brandOwner and fdcId.

On your first render this data might now be loaded yet, so you should default to an empty array if foods is undefined.

It's honestly been a long time since I've used contexts in class components the way that you are doing it. The style of code is very dated. How about using the useContext hook to access the value?

const AddFoodItemList = () => {
  const contextValue = useContext(AddFoodContext);
  console.log(contextValue);

  const listItems = (contextValue.foods || []).map((foods) => (
    <FoodItem
      key={foods.fdcId} // brandOwner isn't unique
      brandOwner={foods.brandOwner}
      fdcId={foods.fdcId}
    />
  ));

  return <div id="AddFoodItemList">{listItems}</div>;
};

Here's a complete code to play with - Code Sandbox Link

const MY_API_KEY = "DEMO_KEY"; // can replace with your actual key

const getUri = (search) => `https://api.nal.usda.gov/fdc/v1/foods/search?api_key=${MY_API_KEY}&query=${encodeURIComponent(search)}`;

const AddFoodContext = createContext({});

const FoodItem = ({ brandOwner, fdcId }) => {
  return (
    <div>
      <span>{fdcId}</span> - <span>{brandOwner}</span>
    </div>
  );
};

const AddFoodItemList = () => {
  const contextValue = useContext(AddFoodContext);
  console.log(contextValue);

  const listItems = (contextValue.foods || []).map((foods) => (
    <FoodItem
      key={foods.fdcId} // brandOwner isn't unique
      brandOwner={foods.brandOwner}
      fdcId={foods.fdcId}
    />
  ));

  return <div id="AddFoodItemList">{listItems}</div>;
};

export default () => {
  const [data, setData] = useState({});

  useEffect(() => {
    fetch(getUri("cheese"))
      .then((res) => res.json())
      .then(setData)
      .catch(console.error);
  }, []);

  return (
    <AddFoodContext.Provider value={data}>
      <AddFoodItemList />
    </AddFoodContext.Provider>
  );
};
Linda Paiste
  • 38,446
  • 6
  • 64
  • 102