Search code examples
reactjstypescriptreact-hookstsxreact-tsx

Declare arguments with interface on typescript react hook


I am trying to create a custom hook that receives 2 typed arguments with an interface but I am getting a message Expected 1 arguments, but got 2, I am not sure if I am declaring the interface wrong or if the file can't be tsx

enter image description here

File index.tsx

const [thisPage, setThisPage] = useState(1)

const changePage = (newNumber?: number): void => {
  console.log(newNumber ?? thisPage)
}

const { goNext, goBack } = useSideButtons(changePage, setThisPage)

File useSideButtons.tsx

import { useEffect, SetStateAction } from 'react'

interface ISideButtons {
  changePage: (newNumber?: number) => void
  setThisPage: (value: SetStateAction<number>) => void
}

interface ISideExports {
  goNext: () => void
  goBack: () => void
}

export default function useSideButtons ({ changePage, setThisPage }: ISideButtons): ISideExports {
  useEffect(changePage, [])

  const goNext = (): void => {
    setThisPage((actual) => {
      const newNumber = actual + 1
      return newNumber
    })
  }

  const goBack = (): void => {
    setThisPage(actual => {
      if (actual > 1) {
        const newNumber = actual - 1
        changePage(newNumber)
        return newNumber
      } else {
        return 1
      }
    })
  }

  return { goNext, goBack }
}

I know that using like this works, but I want to declare an interface to make the code easier to read:

import { useEffect, SetStateAction } from 'react'

interface ISideExports {
  goNext: () => void
  goBack: () => void
}

export default function useSideButtons (
  changePage: (newNumber?: number) => void,
  setThisPage: (value: SetStateAction<number>) => void
): ISideExports {
  useEffect(changePage, [])

  const goNext = (): void => {
    setThisPage((actual) => {
      const newNumber = actual + 1
      localStorage.setItem('instandaThisPage', String(newNumber))
      return newNumber
    })
  }

  const goBack = (): void => {
    setThisPage(actual => {
      if (actual > 1) {
        const newNumber = actual - 1
        changePage(newNumber)
        localStorage.setItem('instandaThisPage', String(newNumber))
        return newNumber
      } else {
        return 1
      }
    })
  }

  return { goNext, goBack }
}

Solution

  • The confusion is due to the destructuring you are doing here: function useSideButtons ({ changePage, setThisPage }: ISideButtons)

    This code means there is one parameter, not two. It is similar to writing

    function useSideButtons (sideButtons: ISideButtons) {
        const changePage = sideButtons.changePage;
        const setThisPage = sideButtons.setThisPage;
        // Rest of your code
    
    }
    

    As you can see in the example above, you only have 1 parameter to the function.

    So instead of passing two parameters like this: useSideButtons(changePage, setThisPage), you probably intended to pass one object containing both values like this: useSideButtons({ changePage, setThisPage })