Home > Mobile >  Attempting to pass states to children component in React Typescript
Attempting to pass states to children component in React Typescript

Time:02-01

I am learning React and Typescript at the same time and while I was working on a project I encountered this TS error. Here is my App.tsx:

import { useState } from "react"

import "./App.css"
import Sidebar from "./components/Sidebar"
import Carousel from "./components/Carousel"
import Today from "./components/Today"

function App() {
  const [selectedDate, setSelectedDate] = useState<Date>(new Date())

  return (
    <div className="w-screen h-screen px-20 py-16">
      <div className="bg-gray-50/50 h-full rounded-2xl flex">
        <Sidebar selectedDate={selectedDate} />
        <div className="flex-col w-full">
          <Carousel
            selectedDate={selectedDate}
            setSelectedDate={setSelectedDate}
          />
          <Today selectedDate={selectedDate} />
        </div>
      </div>
    </div>
  )
}

export default App

and this is the Carousel.tsx:

import React from "react"
import { addDays, getDay, previousMonday } from "date-fns"
import { SlArrowLeft, SlArrowRight } from "react-icons/sl"

import DayBadge from "../elements/DayBadge"

function Carousel(
  selectedDate: Date,
  setSelectedDate: React.Dispatch<React.SetStateAction<Date>>
) {
  const [main, setMain] = React.useState(new Date())

  return (
    <div className="flex-col h-1/3 p-10">
      <div className="mb-5 flex">
        <SlArrowLeft
          className="mt-1 mr-3 cursor-pointer"
          onClick={() => setMain(addDays(main, -7))}
        />{" "}
        Week{" "}
        <SlArrowRight
          className="mt-1 ml-3 cursor-pointer"
          onClick={() => setMain(addDays(main, 7))}
        />
        <div
          className="mx-3 cursor-pointer"
          onClick={() => setMain(new Date())}
        >
          Current week
        </div>
      </div>

      <div className="flex mx-auto">
        <DayBadge day={addDays(main, -3)} setSelectedDate={setSelectedDate} />
        <DayBadge day={addDays(main, -2)} setSelectedDate={setSelectedDate} />
        <DayBadge day={addDays(main, -1)} setSelectedDate={setSelectedDate} />
        <DayBadge day={main} setSelectedDate={setSelectedDate} />
        <DayBadge day={addDays(main, 1)} setSelectedDate={setSelectedDate} />
        <DayBadge day={addDays(main, 2)} setSelectedDate={setSelectedDate} />
        <DayBadge day={addDays(main, 3)} setSelectedDate={setSelectedDate} />
      </div>
    </div>
  )
}

export default Carousel

I am trying to pass the selectedDate and setSelectedDate to the carousel, sidebar and today component. My aim is that every time the selectedDate is updated then the whole app should update using the date selected to fetch for data.
The exact error given is the following:

(property) selectedDate: Date
Type '{ selectedDate: Date; }' is not assignable to type 'IntrinsicAttributes & Date'.
  Property 'selectedDate' does not exist on type 'IntrinsicAttributes & Date'.ts(2322)

I tried to add an extra curly bracket as I thought I was trying to send an object however this other error came out:

Type '{ selectedDate: { selectedDate: Date; }; }' is not assignable to type 'IntrinsicAttributes & Date'. Property 'selectedDate' does not exist on type 'IntrinsicAttributes & Date'.ts(2322)

So I looked around searching for the error to see what could I find but I don't really understand why this is happening. Can someone explain to me the error?

Thanks :D

CodePudding user response:

Your component declaration should looks like this:

function Carousel({
  selectedDate,
  setSelectedDate
}: {
  selectedDate: Date,
  setSelectedDate: React.Dispatch<React.SetStateAction<Date>>
})

CodePudding user response:

The correct way to type the params from the Carousel component is:

function Carousel({
  selectedDate,
  setSelectedDate
}: {
  selectedDate: Date,
  setSelectedDate: React.Dispatch<React.SetStateAction<Date>>
}) {
  ...
}

The reason why it did not work is that you cannot destructure and type the object at the same time, because that's how you rename and destructure at the same time in javascript.

For example, let's say you want to destructure and rename any of the properties from this object:

const person = {
  age: 20,
  name: "John"
}

In this case, if we were to rename the name property to firstName and destructure at the same time, it would be:

const {age, name: firstName} = person

So we would end up with the variables age (20) and firstName (John), and not name.


Additionally, a better way to type the component would be to extract the params into it's own interface or type:

type CarouselProps {
  selectedDate: Date,
  setSelectedDate: React.Dispatch<React.SetStateAction<Date>>
}

function Carousel({
  selectedDate,
  setSelectedDate
}: CarouselProps) {
  ...
}

Here you can find more information about this.

  • Related