Search code examples
javascriptreactjsonclickcomponents

A function passed as an onClick property is passed only once


I am building up an app that enables users to look at the information of movies to study React. I have a component named BoxOffice that has several useState. One of the useState is const [movieDetailPage, setMovieDetailPage].
I pass setMovieDetailPage as the property onClick of the component Movie

In the component Movie, I assign the setMovieDetailPage as an onClick event of a div. When I click the div for the first time, it returns me the default value 0 well. But when I click it the second time, it does not return me anything.

Here are my codes:
BoxOffice.js

import { useEffect, useState } from 'react'

import Movie from '../Movie/Movie'
import BoxOfficeButton from '../BoxOfficeButton/BoxOfficeButton'

import styles from './BoxOfficeStyles'



let data;
function BoxOffice(props) {
  const [containerValue, setContainerValue] = useState(5)
  const [containerValueLimit, setContainerValueLimit] = useState(0)
  const [movieDetailPage, setMovieDetailPage] = useState(0)

  try {
    data = Array.from(JSON.parse(props.data))
    data = data.map(JSON.parse)

    return (
      <>       
        <div style={styles}>
          <BoxOfficeButton value={containerValue} valueLimit={data.length} type='left'/>
          {data.slice(containerValue-5, containerValue).map((movieInfo) => <Movie info={movieInfo} onClick={setMovieDetailPage} />)}
          <BoxOfficeButton value={containerValue} valueLimit={data.length} type='right'/> 
        </div>       
      </>
    )
  }
  catch {
    return <div style={styles}></div>
  }
}

export default BoxOffice

Movie.js

import styles from './MovieStyles'

function Movie(props) {
  function handleClick() {
    const setMovieDetailPage = props.onClick

    setMovieDetailPage((prev) => {
      if (prev == 0) {
        console.log(prev)
      }
    })
  }

  try {
    return (
      <div style={styles} onClick={() => handleClick()}>
        <div>{props.info.title}</div>
      </div>
    )
  }
  catch {
    return (
      <div style={styles}></div>
    )
  }
}

export default Movie

Why does it work only once? What is the possible issue here?


Solution

  • Inside the setter function you are using here:

    function handleClick() {
        const setMovieDetailPage = props.onClick
    
        setMovieDetailPage((prev) => {
          if (prev == 0) {
            console.log(prev)
          }
        })
      }
    

    You are not returning anything inside the setter function. This means that on the first click you are setting the value of the movieDetailPage state to be undefined. Hence why on the next click the condition prev == 0 is no longer met so the console.log() is not executed.

    To fix this simply return a value inside the function

    function handleClick() {
        const setMovieDetailPage = props.onClick
    
        setMovieDetailPage((prev) => {
          if (prev == 0) {
            console.log(prev)
          }
         return // return something here
        })
      }