Home > other >  Prop is an empty object in React child
Prop is an empty object in React child

Time:11-22

I'm trying to add a search bar to a parent component. All the logic is working fine in the console. With every character that is typed in the search field I get fewer results. I try to pass it to a child component to render the card(s) result, but I get a blank card: I can not see data passed.

Parent Component <AllAssets>

class AllAssets extends Component {

  state = {
    cards: [],
    searchField: '',
  }

  async componentDidMount() {
    const { data } = await cardService.getAllCards();
    if (data.length > 0) this.setState({ cards: data });
  }

  addToFavorites = (cardId, userId) => {
    saveToFavorites(cardId, userId)
    toast.error("The asset was added to your favorites.")
  }

  render() {

    const { cards, searchField } = this.state;
    const user = getCurrentUser();

    const filteredAssets = cards.filter(card => (
      card.assetName.toLowerCase().includes(searchField.toLowerCase())));

    console.log(filteredAssets);

    return (
      <div className="container">
        <SearchBox placeholder={"Enter asset name..."}
          handleChange={(e) => this.setState({ searchField: e.target.value })}
        />
        <PageHeader>Assets available for rent</PageHeader>
        <div className="row">
          <div className="col-12 mt-4">
            {cards.length > 0 && <p>you can also add specific assets to your favorites and get back to them later...</p>}
          </div>
        </div>
        <div className="row">
          {!!filteredAssets.length ? filteredAssets.map(filteredAsset => <SearchResult addToFavorites={this.addToFavorites} filteredAsset={filteredAsset} user={user} key={filteredAsset._id} />) :
            cards.map(card => <CardPublic addToFavorites={this.addToFavorites} card={card} user={user} key={card._id} />)
          }
        </div>
      </div >
    );
  }
}

export default AllAssets;

Child Component <SearchResult>

const SearchResult = (addToFavorites, filteredAsset, card, user) => {
  return (
    <div className="col-lg-4 mb-3 d-flex align-items-stretch">
      <div className="card ">
        <img
          className="card-img-top "
          src={filteredAsset.assetImage}
          width=""
          alt={filteredAsset.assetName}
        />
        <div className="card-body d-flex flex-column">
          <h5 className="card-title">{filteredAsset.assetName}</h5>
          <p className="card-text">{filteredAsset.assetDescription}</p>
          <p className="card-text border-top pt-2">
            <b>Tel: </b>
            {filteredAsset.assetPhone}
            <br />
            <b>Address: </b>
            {filteredAsset.assetAddress}
          </p>
          <p>
            <i className="far fa-heart text-danger me-2"></i>
            <Link to="#" className="text-danger" onClick={() => addToFavorites(card._id, user._id)}>Add to favorites</Link>
          </p>
        </div>
      </div>
    </div>
  );
}

export default SearchResult;

When I console.log(filteredAsset) in <SearchResult> I get an empty object. What am I doing wrong?

CodePudding user response:

This line is incorrect:

const SearchResult = (addToFavorites, filteredAsset, card, user) => {

You are passing in positional arguments, not named props. Do this instead:

const SearchResult = ({addToFavorites, filteredAsset, card, user}) => {

In your original code, React attaches all of your props as fields on the first argument. So they would be accessible in the child, but not in the way you're trying to access them. Try logging out the values of each of the arguments in the child, if you're curious to see what happens.

The corrected version passes in a single object with field names that match the names of your props. It's shorthand that's equivalent to:

const SearchResult = (
  {
    addToFavorites: addToFavorites, 
    filteredAsset: filteredAsset, 
    card: card, 
    user: user,
  }
) => {

  • Related