Home > database >  Why is React/TS not properly recognizing my declared type? Type {} Not Assignable to Type ()=>voi
Why is React/TS not properly recognizing my declared type? Type {} Not Assignable to Type ()=>voi

Time:06-12

I basically have a button element pretty far down the component hierarchy so I'm passing a function from my App level downwards so that it can be called onClick within the button. I feel like I've correctly defined both the App function (newTodoCard()) as :()=>void and the prop of child component (onAddTodo()) as :()=>void. I would prefer to avoid defining an entire Interface for one function prop and want to understand why my approach isn't working.

App.tsx

import React from 'react';
import Header from './components/Header';
import Sidebar from './components/Sidebar';
import TodoCard from './components/TodoCard';
import { TodoCardProps } from './components/TodoCard';
import { useState } from 'react';

function App() {
  const[todoCards,setTodoCards] = useState([]);
  let currentTodoCard: TodoCardProps = {title:"",content:""};
  const newTodoCard: ()=>void = ()=>{
    currentTodoCard = {title:"NEW",content:"NEW"};
  }
  return (
    <div className="App">
      <Header/>
      <div className="container">
        <Sidebar {...newTodoCard}/>
        <TodoCard {...currentTodoCard}/>
      </div>
    </div>
  );
}

export default App;

This snippet from above is where the error is:

<Sidebar {...newTodoCard}/>

Sidebar.tsx

import React from 'react'
import TitleCards from './TitleCards'
import SidebarHeader from './SidebarHeader'

const Sidebar = ( onAddTodo: ()=>void) => {
  return (
    <div className="sidebar">
        <SidebarHeader {...onAddTodo}/>
        <TitleCards/>
    </div>
  )
}

export default Sidebar

Additionally, if I change how I pass in the prop to

<Sidebar onAddTodo={newTodoCard}/>

It seems to solve the issue, but this error Type '{ onAddTodo: () => void; }' is not assignable to type 'IntrinsicAttributes & (() => void)'. Property 'onAddTodo' does not exist on type 'IntrinsicAttributes & (() => void)' appears (which from online research is only fixed by using {...prop} as I did originally. I appreciate any help! Thanks.

CodePudding user response:

The specific error you are seeing is because you are trying to use a props spread operator ... on something that isn't an object. newTodoCard is a function. If you want to pass it to <SidebarHeader /> as a prop, you can just do <SidebarHeader onAddTodo={newTodoCard} />.

You would declare a prop in your SidebarHeader component to match the callback that is being passed. The key thing to note here is that the props that are passed to your component is an object with a property called onAddTodo.

interface MyProps {
    onAddTodo: () => void;
}

export function SidebarHeader = (props: MyProps) => {

    return <div>
        <Button onClick={event => props.onAddTodo()} />
    </div>
}

However, your callback isn't going to work as expected the way you have written it. When it is called, it is going to set the value of currentTodoCard, but that is a local variable that has a limited scope. The next time your app re-renders, the App function is going to be called again, and you will get a new instance of currentTodoCard. In order for your callback to work as expected, it is going to need to call setTodoCards or set some other state.

  • Related