Search code examples
reactjscomponents

React Map Error in a component (cannot read the properties of undefined reading id)


This is my code. I don't know why but the error is in the "FriendList" Component

I tired goggling and asking chat gpt but it doesn't work. Thanks.

/* eslint-disable react/no-unescaped-entities */
/* eslint-disable react/prop-types */
import { useState } from "react";

const initialFriends = [
    {
        id: 118836,
        name: "Clark",
        image: "https://i.pravatar.cc/48?u=118836",
        balance: -7,
    },
    {
        id: 933372,
        name: "Sarah",
        image: "https://i.pravatar.cc/48?u=933372",
        balance: 20,
    },
    {
        id: 499476,
        name: "Anthony",
        image: "https://i.pravatar.cc/48?u=499476",
        balance: 0,
    },
];

const App = () => {
    const [showAddFriend, setShowAddFriend] = useState(false);
    const [friends, setFriends] = useState(initialFriends);
    const handleShowAddFriend = () => {
        setShowAddFriend((show) => !show);
    };
    const handleAddFriend = ({ friend }) => {
        setFriends((friends) => [...friends, friend]);
    };

    return (
        <div className="app">
            <div className="sidebar">
                <FriendList friends={friends} />
                {showAddFriend && <FormAddFriend onAddFriend={handleAddFriend} />}
                <Button onClick={handleShowAddFriend}>
                    {showAddFriend ? "Close" : "Add friend"}
                </Button>
            </div>
            <FormSplitBill />
        </div>
    );
};

const Button = ({ children, onClick }) => {
    return (
        <button onClick={onClick} className="button">
            {children}
        </button>
    );
};

const FriendList = ({ friends }) => {
    return (
        <ul>
            {friends.map((friend) => (
                <Friend friend={friend} key={friend.id} />
            ))}
        </ul>
    );
};

const Friend = ({ friend }) => {
    return (
        <li>
            <img src={friend.image} alt={friend.name} />
            <h3>{friend.name}</h3>
            {friend.balance < 0 ? (
                <p className="red">
                    You owe {friend.name} {Math.abs(friend.balance)}$
                </p>
            ) : friend.balance === 0 ? (
                <p>You and {friend.name} are even</p>
            ) : (
                <p className="green">
                    {friend.name} owes you {friend.balance}$
                </p>
            )}
            <Button>Select</Button>
        </li>
    );
};

const FormAddFriend = ({ onAddFriend }) => {
    const [name, setName] = useState("");
    const [image, setImage] = useState("https://i.pravatar.cc/48");

    const handleSubmit = (e) => {
        e.preventDefault();
        if (!name || !image) return;
        const id = crypto.randomUUID();
        const newFriend = {
            id,
            name,
            image: `${image}?=${id}`,
            balance: 0,
        };
        onAddFriend(newFriend);
        setName("");
        setImage("https://i.pravatar.cc/48");
    };

    return (
        <form className="form-add-friend" onSubmit={handleSubmit}>
            <label>Friend name</label>
            <input
                type="text"
                value={name}
                onChange={(e) => setName(e.target.value)}
            />
            <label>Image URL</label>
            <input
                value={image}
                onChange={(e) => setImage(e.target.value)}
                type="text"
            />
            <Button>Add</Button>
        </form>
    );
};

const FormSplitBill = () => {
    return (
        <form className="form-split-bill">
            <h2>Split a bill with X</h2>
            <label>💲 Bill value</label>
            <input type="text" />
            <label>💵 Your expense</label>
            <input type="text" />
            <label>👨🏿‍🤝‍👨🏾 X's expense</label>
            <input type="text" />
            <label>😅 Who is paying the bill</label>
            <select>
                <option value="user">You</option>
                <option value="friend">X</option>
            </select>
            <Button>Split bill</Button>
        </form>
    );
};

export default App;

I am learning from a Udemy course. Here's the error message from the console. App.jsx:62 Uncaught TypeError: Cannot read properties of undefined (reading 'id') at App.jsx:62:45 at Array.map () at FriendList (App.jsx:61:16) console.js:213 The above error occurred in the component: your text at FriendList (http://localhost:5173/src/App.jsx?t=1705498582948:92:23) at div at div at App (http://localhost:5173/src/App.jsx?t=1705498582948:41:45)


Solution

  • You're passing the onAddFriend function as a prop to FormAddFriend. In FormAddFriend, you are trying to call onAddFriend as a function with an argument, but you have defined it as an object destructuring parameter.

    Pass the onAddFriend function directly without wrapping it inside an object.

    const handleAddFriend = (friend) => {
        setFriends((friends) => [...friends, friend]);
      };