Reactjs trigger onClick function without click in functional component
I’m using functional component in react js , my onClick function triggers with component rendering without click on my li element ; this is my parent component that passed the handleCallDetails function as props to child component:
export default function Cartable(){ const [items , setItems] = useState(null); const [details , setDetails] = useState(null); function handleCallDetails(id){ if(items !== null && details === null){ let d = items.find(x => { return x.id === id; }); } } useEffect(() => { axios.get(`/workflows/${mode}` ,{ params : { OrganizationId : "FE905B40-DA6E-4A81-8A4F-B447AA6B0EA3" , Type : 2 , sortorder : "desc" , pageIndedx : 1 , pageSize : 10 } }).then(response => { // console.log('response : ***************** ' , response); setItems(response.data.data); }).catch(error => { console.log('error : ****************** ' , error); }); } , [mode]); return ( <Grid container spacing={2}> <Grid item xs={12} sm={4} md={3}> <div className="drt_RightSide drt_segment"> <h4 className="drt_RightSideTitle"> <i className="far fa-inbox"></i> کارتابل </h4> <ul> {/* <li> <i class="far fa-inbox"></i> <span>درخواست ها</span> </li> */} <li onClick={() => {setMode('pending');}}> <i className="fas fa-exclamation"></i> <span><FormattedMessage id="CARTABLE_PENDING" /></span> <span className="drt_badge_warning drt_NotifNum">5</span> </li> <li onClick={() => {setMode('approved');}}> <i className="far fa-check"></i> <span>تایید شده</span> </li> <li onClick={() => {setMode('rejected');}}> <i className="far fa-times"></i> <span>رد شده</span> <span className="drt_badge_error drt_NotifNum">7</span> </li> <li> <i className="far fa-bell"></i> <span>خارج از فرآیند</span> </li> </ul> </div> </Grid> <Grid item xs={12} sm={8} md={9}> <div className="drt_LeftSide drt_segment"> */} {/* cartbale list */} <CartableList items={items} callDetails={handleCallDetails}/> </div> </Grid> </Grid> ); }
and it is my child compnent that use onClick function that named callDetails:
export default function CartableList(props){ const [showbox , setShowbox] = useState(false); const [age, setAge] = useState(''); const handleChange = (event) => { setAge(event.target.value); }; function handleFilterBox(){ setShowbox(!showbox); } return ( <Fragment> {/* cartable list */} <div style={{direction : "ltr"}}> <Scrollbars style={{ height: 400 }}> { props.items && props.items !== undefined ? props.items.map(function(item , index){ return ( <div className="drt_clearfix drt_CartableItem" key={index} onClick={(props.callDetails)(item.id)}> {/* <div className={clsx(drt_ItemStar , item.star ? drt_IsStared : '')}> <span><i className={clsx(item.star ? "fas fa-star" : "fal fa-star")}></i></span> </div> */} <div className="drt_ItemImg"> <span> <img alt={userImg} src={item.pictureUrl !== undefined && item.pictureUrl !== null ? item.image : userImg} /> </span> </div> <div className={clsx("drt_ItemName" , !item.isSeen ? "drt_IsNotSeen" : '')}> {item.issuerFirstName} <br /> {item.issuerLastname} </div> <div className="drt_ItemIcon"> <Tooltip title={(props.moduleType)(item.type).name}> <span className={item.isSeen ? "drt_badge_default" : "drt_badge_primary"}> <i className={(props.moduleType)(item.type).icon} /> </span> </Tooltip> </div> <div className={clsx("drt_ItemDesc" , !item.isSeen ? "drt_IsNotSeen" : '')}> {item.objectTitle} </div> <div className="drt_ItemStatus"> <span className={(props.stateClass)(item.status)}> {(props.stateTitle)(item.status)} </span> </div> <div className={clsx("drt_ItemDate" , !item.isSeen ? "drt_IsNotSeen" : '')}> <p> <span> {item.issuerTime} </span> <span> {item.issuerDate} </span> </p> <i className="fal fa-clock" /> </div> </div> ); }) : '' } </Scrollbars> </div> </Fragment> ); }
please help me to solve this problem without convert my functional component to class component and binding my function
The correct way is this. You need to use arrow function or else react will understand that you want to execute the function at load
wrong
<div className="drt_clearfix drt_CartableItem" key={index} onClick={(props.callDetails)(item.id)}>
correct
<div className="drt_clearfix drt_CartableItem" key={index} onClick={() => props.callDetails(item.id)}>
Change from
onClick={() => {setMode('rejected');}}
to
onClick={() => setMode('rejected')}
Also
<div className="drt_clearfix drt_CartableItem" key={index} onClick={() => props.callDetails(item.id)}>
But where did you define the const [mode, setMode]
state
It seems you exec your callback function immediately as it renders based on your code:
onClick={(props.callDetails)(item.id)}
It’s supposed to be:
onClick={() => props.callDetails(item.id)}
Is that the issue?
It’s mainly because of piece of code onClick={(props.callDetails)(item.id)}
in your child component. This code is actually executing callDetails function and passing the item.id value immediately. One way to handle this is to wrap your function.
onClick={() => {props.callDetails(item.id)}}
A simple reason as to why onClick
is not called when it is wrapped is because it is not directly passing in any value when initialised.