javascriptreactjsreact-nativereact-propsdestructuring

Receiving props through Destructuring/Function Component - Error "Missing in prop validation"


I've been working at this for about two days and I'm going to continue to work on it but thought it might be time to get some guidance while I continue to chip away at it. This is my first react project and I'm a bit confused. I've been taking classes online and my instructor's example for receiving props through destructuring with function components I've followed and re-written again and again but I keep getting the error "Missing in prop validation". I am using ESLint.

I really like to code and I'm not the fastest learner, but would like to understand what I'm doing wrong.

The instructor's code example does not use .props at all so I'm confused. I know there's different ways to receive props, so I'm specifically confused about receiving props through destructuring. Thank you for any guidance. I've referenced these articles alongside a lot of stack overflow questions:

https://www.npmjs.com/package/prop-types https://legacy.reactjs.org/docs/components-and-props.html https://codedamn.com/news/reactjs/best-practices-for-passing-props-between-components https://dev.to/colocodes/react-class-components-vs-function-components-23m6

import PageNav from "../components/PageNav";
import "./Work.module.css";

const galleryData = [
    {
        name: "Pixel Art 1",
        description: "Blah blah blah",
        openModal: false,
    },
    {
        name: "Pixel Art 2",
        description: "Blah blah bla",
        openModal: false,
    },
    {
        name: "Pixel Art 3",
        description: "Blah bah blah",
        openModal: false,
    },
];

export default function PixelArt() {
    return (
        <main className="workPageGrid">
            <PageNav />
            <div className="galleryList">
                <GalleryList />
            </div>
        </main>
    );
}

function GalleryList() {
    const galleries = galleryData;
    console.log(galleries);

    const numGallery = galleries.length;
    console.log(numGallery);

    return (
        <main className="galleryList">
            <h2>wtf</h2>

            {numGallery > 0 ? (
                <ul className="galleries">
                    {galleries.map((gallery) => (
                        <Gallery galleryObj={gallery} key={gallery.name} />
                    ))}
                </ul>
            ) : (
                <p>fml :)</p>
            )}
        </main>
    );
}

function Gallery({ galleryObj }) {
    console.log(galleryObj);

    if (galleryObj.openModal) return null;

    return (
        <li className={`gallery ${galleryObj.openModal ? "open-modal" : ""}`}>
            {" "}
            <div>
                <h2>{galleryObj.name}</h2>
                <p>{galleryObj.description}</p>
            </div>
        </li>
    );
}

Specifically the error EsLint is throwing is:

galleryObj
galleryObj.openModal
galleryObj.name
galleryObj.description
are missing in props validation eslint(react/prop-types)

Solution

  • The instructor is probably not using ESLint on their project, or is using ESLint but without the React rules configured.

    The code, if allowed to compile if you did not have ESLint, would work fine. The ESLint rules you are using, like react/prop-types are trying to encourage best practices.

    In this case, this rule specifically requires that every component that takes in props utilises the React prop types feature. In reality, this is optional. It is the ESLint rule that is making it required and preventing the code from compiling, as it does not conform to the best practices this ESLint rule is trying to enforce.

    Declaring prop types on a component means that it's harder to misuse a component, since the type of data for each prop (and that includes things like whether the prop is optional or not), is validated by that prop type configuration at runtime. Meaning if someone (in this case, as the sole dev, that's you) uses the component incorrectly, they get an error saying so rather than some indeterminate buggy behaviour.

    In your case, only the Gallery component takes in props, specifically, it takes in the galleryObj prop which is an object that contains name, description and openModal keys. The first two should be a string and the last one should be a boolean. So we can define the prop types like so:

    // Add new import line
    import { PropTypes } from "prop-types"; 
    
    // ... Existing code
    
    function Gallery({ galleryObj }) {
        console.log(galleryObj);
    
        if (galleryObj.openModal) return null;
    
        return (
            <li className={`gallery ${galleryObj.openModal ? "open-modal" : ""}`}>
                {" "}
                <div>
                    <h2>{galleryObj.name}</h2>
                    <p>{galleryObj.description}</p>
                </div>
            </li>
        );
    }
    
    Gallery.propTypes = {
        galleryObj: PropTypes.shape({
            name: PropTypes.string.isRequired,
            description: PropTypes.string.isRequired,
            openModal: PropTypes.bool.isRequired,
        }).isRequired,
    
    }
    

    Note you will need to add the prop-types NPM package to your project dependencies if you don't have it already.

    It's important to add that it's also ok to think about the tradeoffs of each linting rule and decide if in your case it is worth the extra effort (and disable it if it is not). The default rule set may be overzealous in a situation where you are the only developer; but at the same time, it might give you an idea of the things you should think about from a learning perspective.