简体   繁体   中英

How to pass props to subcomponent in Reactjs

I am attempting to pass props from a parent component function to a child in React without any luck. I am utilizing the React Data Table Component 's filtering functionality . The example documentation in Storybook is great, however I want to change the search box into a list of tags, that when clicked, will filter the data table just the same.

The data I'm trying to parse into individual "tags" is structured like this:

  [{"id":"09090","first_name":"Cynthia","last_name":"McDonald","email":"email1@gmail.com","profile_url":"https:myprofile.com/1","types":["professor","science"]},
{"id":"03030","first_name":"Ryan","last_name":"Burke","email":"email2@gmail.com","profile_url":"https://myprofile.com/2","types":["student","science"]},
{"id":"05050","first_name":"Stewart","last_name":"Hook","email":"email3@gmail.com","profile_url":"https://myprofile.com/3","types":["professor","math"]}]

I am trying to create a unique tag list of the "types" attribute that acts as a filter onClick instead of onChange, just like the original search textbox example. So based on the sample data, we would end up with tags for professor, science, student, and math.

If you look at the code in Storybook, more specifically, line 45:

const subHeaderComponentMemo = React.useMemo(() => 
<Filter onFilter={value => setFilterText(value)} />, []);

My data is loaded via an API call and I am trying to pass that data to the subHeaderComponentMemo with props, ie,

const subHeaderComponentMemo = React.useMemo(() => 
<Filter data={people} onFilter={value => setFilterText(value)} />, []);

I am then trying to receive and loop through that data on line 20 and am replacing most of that code so that it will render the unique tags from the types attribute of the data.

Storybook code:

const Filter = ({ onFilter }) => (  
<TextField id="search" type="search" role="search" placeholder="Search Title" onChange={e => onFilter(e.target.value)} />
);

My failed code

const Filter = ({props, onFilter }) => {
  // Get a unique array of types
  const types = [...new Set(props.types.map(type => type))];

  return types.map(type => (
    <span
      className="badge badge-primary"
      onClick={() => onFilter({ type })}
      onKeyDown={() => onFilter({ type })}
      tabIndex="0"
      role="button"
    >
      {type}
    </span>
  ));
};

This is of course resulting in an epic fail. The module isn't even displaying.

I'm new to React, so any insight/help would be greatly appreciated.

Updated code based on feedback

const Filter = ({ data, onFilter }) => {
  console.dir(data);
  if (data.length === 0) {
    return <div>No data</div>;
  }

  const types = [...new Set(data.types.map(type => type))];

  return (
    <>
      {types.map(type => (
        <span
          className="badge badge-primary"
          onClick={() => onFilter({ type })}
          onKeyDown={() => onFilter({ type })}
          tabIndex="0"
          role="button"
        >
          {type}
        </span>
      ))}
      ;
    </>
  );
};

One of the errors I got when I made the changes was "cannot read property of 'map' undefined", which I equated to the fact that this component may be rendering before the data gets there and it is empty. So I added an if with a return in case this happens.

I also rewrote the return the statement in Filter based on the feedback because it did look like it would loop and try to render a new component for each iteration.

However, the issue still stands with the data not being present. The table is now loading with the data, but this component is just returning the "No data" div as if nothing ever happened. I'm not sure if this is due to the useMemo hook or what. Besides that, no errors.

Thank you for your time and feedback.

Another update

UseMemo needed the prop to be a dependency in its array... I'm finally seeing data when I console.log it.

const subHeaderComponentMemo = useMemo(
    () => <Filter data={people} onFilter={value => setFilterText(value)} />,
    [people]
  );

However, I'm getting the 'map' undefined error again, as if my data is not in the structure I expect it to be in. I have not changed it and this is the code I'm using to try to access it (as shared before):

  const types = [...new Set(data.types.map(type => type))];

Thanks again everyone... getting closer!

you should rewrite you component signature to match the one you are trying to use

const Filter = ({props, onFilter }) => // you are expecting a props name props

<Filter data={people} onFilter={value => setFilterText(value)} />, []); // you are passing data and setFilterText 

so you should change it to

const Filter = ({data, onFilter }) =>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM