skip to Main Content

I’m following Jonas Schmedtmann’s full-stack crash course, and everything is fine. But in this part, I’m receiving a React runtime error (TypeError: Cannot read properties of undefined (reading 'color')) while I’m coding everything that he codes.

Error is related to this part of the component I paste below:

<span
    className="tag"
    style={{
        backgroundColor: CATEGORIES.find((cat) => cat.name === fact.category)
            .color,
        }}
    onClick={() => setCurrentCategory(fact.category)}>
    {fact.category}
</span>

This is the full component.

function Fact({ fact, setCurrentCategory, setFacts }) {
    const [isUpdating, setIsUpdating] = useState(false);
    async function handleVote(vote) {
        if (vote) {
            setIsUpdating(true);
            const { data: updatedFact, error } = await supabase
                .from("facts")
                .update({ [vote]: fact[vote] + 1 })
                .eq("id", fact.id)
                .select();
            if (!error) {
                setIsUpdating(false);
                setFacts((facts) =>
                    facts.map((f) => (f.id === fact.id ? updatedFact[0] : f))
                );
            }
        }
    }

    return (
        <li className="fact">
            <p>
                {fact.text}
                <a
                    className="source"
                    href={fact.source}
                    target="_blank"
                    rel="noreferrer">
                    (Source)
                </a>
            </p>
            <span
                className="tag"
                style={{
                    backgroundColor: CATEGORIES.find((cat) => cat.name === fact.category)
                      .color,
                  }}
                onClick={() => setCurrentCategory(fact.category)}>
                {fact.category}
            </span>
            <div className="vote-buttons">
                <button
                    onClick={() => handleVote("vote_interesting")}
                    disabled={isUpdating}>
                    👍 {fact.vote_interesting}
                </button>
                <button
                    onClick={() => handleVote("vote_mindBlowing")}
                    disabled={isUpdating}>
                    🤯 {fact.vote_mindBlowing}
                </button>
                <button onClick={() => handleVote("vote_false")} disabled={isUpdating}>
                    ⛔ {fact.vote_false}
                </button>
            </div>
        </li>
    );
}

So, every "fact" object, has a "category" property. Categories and their colors are also defined in an array like this:

const CATEGORIES = [
    { name: "technology", color: "#3b82f6" },
    { name: "science", color: "#16a34a" },
    { name: "finance", color: "#ef4444" },
    { name: "society", color: "#eab308" },
    { name: "entertainment", color: "#db2777" },
    { name: "health", color: "#14b8a6" },
    { name: "history", color: "#f97316" },
    { name: "news", color: "#8b5cf6" }
];

The autocompletion of VS code also recommends the ‘color’ property to use at the line which gives the error, but nothing works.

This is the link of the full file of code.

I have no idea why I’m receiving this error.

2

Answers


  1. Array.find potentially returns undefined if there is not any matching array element that passes the predicate function.

    Return value

    The first element in the array that satisfies the provided testing
    function. Otherwise, undefined is returned.

    You should guard against undefined accesses. One way to do this is to use the Optional Chaining Operator on the color property.

    CATEGORIES.find((cat) => cat.name === fact.category)?.color
    

    If necessary, it’s common to also use the Nullish Coaliscing Operator to provide a fallback value in case a matching element color is not found, i.e. if it is null or undefined.

    Example:

    CATEGORIES.find((cat) => cat.name === fact.category)?.color ?? "#fff" // white
    

    If it is unexpected that the fact.category is not a value defined in your CATEGORIES array, then either update CATEGORIES to include the missing name/category color value, or double-check your fetched facts data is correct.

    Login or Signup to reply.
  2. It’s better to add a question mark ? before .color you wrote, to avoid any runtime errors and handle everything until react fully loads.
    The better code could be something like below:

        style={{ backgroundColor: CATEGORIES.find((cat) => cat.name === fact.category)?.color }}

    If you want to add a default value to the background color you can add something like || 'red' after the .color you wrote.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search