2

I set button onClick as a parameter in the child component and drag and use onClick in the parent component.

The child component Room .

type Props = {
 items?: [];
 onClick?: any; 
}

const Room = ({ onClick, items: [] }: Props) => {

  return (
  <div>
    {items.length ? (
    <>
     {items.map((item: any, index: number) => {
      return (
       <>
         <button key={index} onClick={() => { console.log('hi'); onClick }}>{item.name}</button>
       </>
   )
  }
    </>    
  )
  </div>
 )
}

This is the parent component.

const LoadingRoom = () => {

const handleWaitingRoomMove = (e: any) => {
      e.preventDefault();
      console.log('Hello Move')
    }


  return (
  <>
    <Room
     items={[
           {
              name: "Waiting Room",
              onClick: {handleWaitingRoomMove}
            },
            {
              name: "Host Room",
            },
  ]}
  >
     
    </Room>
  </> 
)
} 

I want to call parent component's onClick handleWaitingRoomMove but it's not getting called.

However, console.log('hi') on the button is called normally whenever the button is clicked. Only button is not called. Do you know why?

0

3 Answers 3

1

onlick is a attribute to the child element. so move it outside of the items array

 <Room
    
     onClick={handleWaitingRoomMove}
     items={[
           {
              name: "Waiting Room",
            },
            {
              name: "Host Room",
            },
  ]}
  >

In the child, missing () for onClick

onClick={(ev) => { console.log('hi'); onClick(ev) }}

Demo

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks for the answer, but onClick should be paired with name .
Called when the Waiting Room name button is clicked, and called differently when the Host name button is called.
see the updated demo
1

You are passing onClick in items, not direct props

<button key={index} onClick={item.onClick}>{item.name}</button>

so your component will be

type Props = {
 items?: [];
}

const Room = ({ items: [] }: Props) => {

  return (
  <div>
    {items.length ? (
    <>
     {items.map((item: any, index: number) => {
      return (
       <>
         <button key={index} onClick={item.onClick}>{item.name}</button>
       </>
   )
  }
    </>    
  )
  </div>
 )
}

Comments

1

It would probably be more advantageous to have one handler that does the work, and use that to identify each room by type (using a data attribute to identify the rooms). That way you keep your data and your component logic separate from each other. If you need to add in other functions at a later stage you can.

const { useState } = React;

function Example({ data }) {

  // Handle the room type by checking the value
  // of the `type` attribute
  function handleClick(e) {
    const { type } = e.target.dataset;
    switch (type) {
      case 'waiting': console.log('Waiting room'); break;
      case 'host': console.log('Host Room'); break;
      case 'guest': console.log('Guest Room'); break;
      default: console.log('Unknown room'); break;
    }
  }

  // Keep the room data and the handler separate
  return (
    <div>
      {data.map(obj => {
        return (
          <Room
            key={obj.id}
            data={obj}
            handleClick={handleClick}
          />
        );
      })}
    </div>
  );

}

// Apply a data attribute to the element
// you're clicking on, and just call the handler
// `onClick`
function Room({ data, handleClick }) {
  const { type, name } = data;
  return (
    <button
      data-type={type}
      onClick={handleClick}
    >{name}
    </button>
  );
}

const data = [
  { id: 1, type: 'waiting', name: 'Waiting Room' },
  { id: 2, type: 'host', name: 'Host Room' },
  { id: 3, type: 'guest', name: 'Guest Room' }  
];

ReactDOM.render(
  <Example data={data} />,
  document.getElementById('react')
);
button:not(:last-child) { margin-right: 0.25em; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
<div id="react"></div>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.