dchisholm125
dchisholm125

Reputation: 13

Why do I need the extra dot notation when passing an array to a prop in React.JS?

I'm newer to React.js and JavaScript syntax, but didn't find a question answering the syntax I'm confused by in the below, so here it goes!

When using an array in React.js, why do I need to use additional dot notation on the passed prop to call a property within an array?

For example, In the Content component, why do I have to type part.parts[0].name in the below when in Java/C# I could just type parts[0].name ? If I don't do the above, I get a "parts[0].name is undefined" error.

The below code is from an exercise, so the intent is for me to sort through the weird logic and fix bugs as an exercise in correcting bad code. It's not pretty, but my solution below runs OK and there is more code that I'm not including, and I'm wondering why I have to use the additional dot notation... any explanation appreciated!

Let me know if my logic is wrong (and the structure of the code is terrible, I know), but if I'm passing the 'course.parts' array directly to the Content component, shouldn't JavaScript be able to grab the name and exercises properties when I pass the individual part to the Part component?

 const App = () => {
      const course = {
        name: 'Half Stack application development',
        parts: [
            {
            number: '1'
            name: 'Fundamentals of React',
            exercises: 10
          },
          {
            number: '2'
            name: 'Using props to pass data',
            exercises: 7
          },
          {
            number: '3'
            name: 'State of a component',
            exercises: 14
          }
        ]
      }
    
      return (
        <div>
          <Header course={course.name} />
          <Content parts={course.parts} />
          <Total parts={course.parts} />
        </div>
      )
    }

const Part = (part) => {
  return (
    <>
      <h2>Part {part.number}: {part.name}</h2>
      <h3>{part.exercises} exercises</h3>
    </>
      )
}
    
    const Content = (parts) => {
      console.log(parts[0])
      return (
        <>
          <Part part={parts[0]} name={parts.parts[0].name} exercises={parts.parts[0].exercises} number={parts.parts[0].number} />
        </>
       )
     }

Upvotes: 0

Views: 671

Answers (3)

Ritwik Math
Ritwik Math

Reputation: 44

All the passed data are stored in a props object. You have to access the passed key like parts in your case through props object. You can use destructuring like const Part = ({ parts }) =>. Take some time and read the documentation.

Upvotes: 0

Borris Wiria
Borris Wiria

Reputation: 476

<Content parts={course.parts} />

Basically in React, this line means a function that has parameter object like function(params) and in that line, it will be like Content({ parts: course.parts })

so your code const Content = (parts) => {...} is the function that accept that params.

To make it more understandable. you can rename the parts in the bracket to be params or usually props in React.

so props is an object.. you can do something like this instead..

const Content = ({ parts }) => {...} which means destructing (ES6 way) the object to the parts. then you can use it directly parts[0].name

Sorry for the weird explanation.

Upvotes: 0

T.J. Crowder
T.J. Crowder

Reputation: 1074505

The first argument passed to a component function is an object with properties for each of the component's props. So if you call:

<Content parts={x} />

...the Content function is called with an object with a parts property on it. That's so if there are other properties, they can be passed all together.

It's fairly common with react function components to use object destructuring to pick out the desired props, like this:

const Content = ({parts}) => {
//               ^−−−−−^−−−−−−−−−−−−−−−− object destructuring
    return (
        <>
            <Part part={parts[0]} name={parts[0].name} exercises={parts[0].exercises} number={parts[0].number} />
        </>
    );
};

That's functionally equivalent to:

const Content = (props) => {
    const parts = props.parts;
    return (
        <>
            <Part part={parts[0]} name={parts[0].name} exercises={parts[0].exercises} number={parts[0].number} />
        </>
    );
};

Side note: There's no need to use a fragment when you're returning just one element:

const Content = ({parts}) => {
    return <Part part={parts[0]} name={parts[0].name} exercises={parts[0].exercises} number={parts[0].number} />;
};

or

const Content = ({parts}) => {
    return <Part
        part={parts[0]}
        name={parts[0].name}
        exercises={parts[0].exercises}
        number={parts[0].number}
    />;
};

And if you're already passing the part, then it seems unnecessary to pass name, exercises, and number separately; Part should be able to get them from the object it receives as its part property. WHich would give us:

const Content = ({parts}) => {
    return <Part part={parts[0]} />;
};

Upvotes: 1

Related Questions