BEDev
BEDev

Reputation: 739

How can I pass the Child name prop to Parent array

I have a list of Child objects mapped from my Parent component in my React App.

When a Child item is clicked, I need the props.name of that item to be pushed to the selectedItems array in the Parent component via the handleClick function.

How can I achieve this?

function Parent() {
  let selectedItems = [];
  const result = Data.filter((e) => selectedItems.includes(e.id));

  return (
    <div className="App">
      <main className="products-grid flex flex-wrap">
        {Data.map((item, i) => {
          return <Child 
          key={item.id} 
          name={item.name} />
        })}
      </main>
    </div>
  );
}
export default App

const Child = (props) => {
  const [clickCount, setClickCount] = useState(0);

  function handleClick() {
    setClickCount(prevClickCount => prevClickCount + 1);
  }

  return (
    <div 
    className="product"
    onClick={() => handleClick()}
    >
      <p>{props.name}</p>
      <p>{clickCount > 0 ? <p>Selected: {clickCount}</p> : <p>Not Selected</p>}</p>
      <img src={props.img} alt="" />
    </div>
  );
}

Upvotes: 0

Views: 104

Answers (2)

Tyler Watts
Tyler Watts

Reputation: 193

I would recommend using hooks for the 'selectedItems' in the parent component, as to trigger a re-render when the name changes.

You can pass functions from the parent to the child component using props.

Below I've passed the 'addToSelectedItems' function down to the child and triggered it in the handleClick method.

const Parent = () => {

  const [selectedItems, setSelectedItems] = useState([]);
  
  function addToSelectedItems(name){
     setSelectedItems([...selectedItems, name]);
  }

  return (
    <div className="App">
      <main className="products-grid flex flex-wrap">
        {Data.map((item, i) => {
          return <Child 
          key={item.id} 
          name={item.name}
          addToSelectedItems={addToSelectedItems}
          />
        })}
      </main>
    </div>
  );
}
export default App

const Child = (props) => {
  const [clickCount, setClickCount] = useState(0);

  function handleClick(name) {
    setClickCount(prevClickCount => prevClickCount + 1);
    props.addToSelectedItems(name);
  }

  return (
    <div 
    className="product"
    onClick={(props.name) => handleClick(props.name)}
    >
      <p>{props.name}</p>
      <p>{clickCount > 0 ? <p>Selected: {clickCount}</p> : <p>Not Selected</p>}</p>
      <img src={props.img} alt="" />
    </div>
  );
}

Upvotes: 1

mttetc
mttetc

Reputation: 745

I'd do something like this, but I have not tested it, it might need some fine tuning

function Parent() {
  let selectedItems = [];
  const result = Data.filter((e) => selectedItems.includes(e.id));
  const [clickCount, setClickCount] = useState(0);
  
  function handleClick(name) {
    setClickCount(prevClickCount => prevClickCount + 1);
    selectedItem.push(name)
  }
  
  return (
    <div className="App">
      <main className="products-grid flex flex-wrap">
        {Data.map((item, i) => {
          return <Child 
          key={item.id} 
          name={item.name}
          clickCount={clickCount}
          handleClick={handleClick} />
        })}
      </main>
    </div>
  );
}
export default App;

const Child = (props) => {
  let { handleClick, name, clickCount, img } = props

  return (
    <div 
    className="product"
    onClick={() => handleClick(name)}
    >
      <p>{name}</p>
      <p>{clickCount > 0 ? <p>Selected: {clickCount}</p> : <p>Not Selected</p>}</p>
      <img src={img} alt="" />
    </div>
  );
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

Upvotes: 0

Related Questions