Home > Enterprise >  React.js JS Sending Array as a property to an element turns the array into an object
React.js JS Sending Array as a property to an element turns the array into an object

Time:08-26

I'm attempting to understand why sending an array as a prop to another element transforms it into an object with a value of the array but I would like some help understanding the why and whether it is a universal JavaScript 'quirk' or if it is to do with React and props. The next paragraph is context and can be skipped

The way this part of my app works is that I have a mapping function in my navigation element that goes through an array of all the navigation items. it adds a list item for each nav item and then uses a method to check if the nav item has a 'subMenu' property and if so it maps the values in the submenu to an array and sends the array to a DropDown element as a prop that will then map those values into list items

However I noticed through logging when I send the array as a prop to the DropDown element it becomes an object with a single value of the array. The array "subMenu" goes from ['Test', 'Test2'] to an object {subMenu: Array(2)}. Took me a bit to realise but the array is clearly being converted into an object with one value (the array) when supplied as a prop

The same variable being logged differently in the element it was created in and the element it is sent to

//The list of submenu navigation items being mapped to an array and provided to dropdown
const subMenu = (navItem) => {
   
    if (navItem.hasOwnProperty('subMenu')) {//Check if it has a sub menu

        const subMenu = navItem.subMenu.map((menu) => {
            return menu.route;/A string that is just the text of the submenu item
        })
        console.log(subMenu);//Logging the simple array of strings, is logged as ['Test', 'Test2']
        return <DropDown subMenu={subMenu} />//Sending the array to a DropDown element
    }
}

The DropDown element in its own file

const DropDown = (argument) => {
    console.log(argument);//Expected to be ['Test', 'Test2'] the exact same as the provided argument but is actually {subMenu: Array(2)}
    return (
        <ul>
            {argument.subMenu.map((navItem) => {//Have to access the value "subMenu" of the object that the array was converted into
                return console.log(navItem)
            })}
        </ul>
    )
    
}

export default DropDown;

I wanted to know two things. Is this a universal javacript thing, and is there something happening behind the hood that I should know that may help me in the future?

Mostly I'm using this post to help any future aspiring devs who can't figure out why their array isn't working when used as an argument, it took me a while to figure out why my app was crashing. Any explanation would be great. Thank you

CodePudding user response:

This has to do with React and props (and not with JavaScript itself). You pass a value (i.e. prop to a child component) and props itself is an object. Instead of writing argument you could also write:

 const DropDown = (props) => {...}

So basically you can handle props in different ways.

Option 1

 const DropDown = (props) => {
        return (
            <ul>
                {props.subMenu.map((navItem) => {
                   ...
                })}
            </ul>
        )
        
    }

Option 2

const DropDown = (argument) => {
    const subMenu = argument.subMenu;
    return (
        <ul>
            {subMenu.map((navItem) => {
               ...
            })}
        </ul>
    )
    
}

Option 3: with object destructuring

    const DropDown = (argument) => {
    const { subMenu } = argument
    return (
        <ul>
            {subMenu.map((navItem) => {
               ...
            })}
        </ul>
    )
    
}

Option 4: destructure props inline

const DropDown = ({ subMenu }) => {
    return (
        <ul>
            {subMenu.map((navItem) => {
               ...
            })}
        </ul>
    )
    
}

CodePudding user response:

Your DropDown element received all the props you sent it as an object where the key is the name of your prop so if you also send a classname for example, the argument received will also contains it so the argument will then be: { classname: '...', subMenu: [...] }. It's that way else DropDown wouldn't know how to dispatch the different props it gets (specially if some are facultative).

You can directly get your subMenu array by spreading your parameters (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax)

const DropDown = ({subMenu}) => {

CodePudding user response:

Ok so in react the first param of a component in react is an object that contains all the props that you have passed so to access your subMenu you can do this:

const DropDown = ({subMenu}) => {
console.log(subMenu);
return (
    <ul>
        {subMenu.map((navItem) => {
            console.log(navItem)
        })}
    </ul>
)

}

CodePudding user response:

A child accepts custom props which are stored in the "props" object. In your case, the "props" object is replaced by "argument".

This way, if your child looks like:

const Parent = () => {
    return <Child loading={true} data={someData} />
}

You may access each prop in the child like this, as to avoid "props.loading" and "props.data":

  const Child = (props) => {
    console.log(props) // will show props: { data: [your_Data], loading: true }

    // extract your props as such:
    const { loading, data } = props;

    return <ul>
        {data.map((navItem) => {//Have to access the value "subMenu" of the object that the array was converted into
            return console.log(navItem)
        })}
    </ul>
 }

If you wish to skip the const {loading, data} = props, you may do the following:

const Child = ({loading, data}) => {...}
  • Note: I have replaced your "sub_menu" prop with "data". "Loading" is only there for demonstration purposes.

CodePudding user response:

I think you are not understanding it in correct way.

In order to pass a value from one component to another the values are passed as key value pairs. These keys, values are then extracted using the key which is assigned in the first component.

For instance,

<DropDown subMenu={subMenu} />

In the above line of code you are assigning the array to a key called "subMenu". So when you want to use the array subMenu(['Test', 'Test2']) you have to access it using the name assigned to it such as subMenu.

The key subMenu can be of any name. Example - it can be items or values or array or anything.

Because these values are assigned to key, you will be able to extract them from second component using their keys.

Without this you will not be able to extract them. For instance there are 2 arrays with different values, the system can not understand which array you want until you specify them with a name.

So to solve this key values are used and are accessed in props. The below example shows you the correct way of extracting them.

In first component the array is assigned to key items.

<DropDown items = {subMenu} />

In the second(Dropdown) component you can access the array by using the key "items".

const { items } = props;

I hope this answers your question.

CodePudding user response:

this will give you a better understanding of how props work in reactjs components-and-props

in your case u can do it like this:-

 const DropDown = (argument) => {
        const {subMenu}=argument;
    return (
        <ul>
            {subMenu.map((navItem) => {//Have to access the value "subMenu" of the object that the array was converted into
                return console.log(navItem)
            })}
        </ul>
    )
    
}
  • Related