Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

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

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:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

<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.

>Solution :

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.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading