2

I am adding TypeScript to my React TodoApp and ran into the following error with the event handler: HandlerCreateTodo:

ERROR in src/TodoTable.tsx:107:21
TS2322: Type '(event: MouseEventHandler<MouseEvent>) => void' is not assignable to type 'MouseEventHandler<Element>'.
  Types of parameters 'event' and 'event' are incompatible.
    Type 'MouseEvent<Element, MouseEvent>' is not assignable to type 'MouseEventHandler<MouseEvent<Element, MouseEvent>>'.
      Type 'MouseEvent<Element, MouseEvent>' provides no match for the signature '(event: MouseEvent<React.MouseEvent<Element, MouseEvent>, MouseEvent>): void'.
    105 |                     enterTodo={ enterTodo }
    106 |                     handleEnterTodo={ handleEnterTodo }
  > 107 |                     handleCreateTodo={ handleCreateTodo }
        |                     ^^^^^^^^^^^^^^^^
    108 |                     handleClearTodos= { handleClearTodos }
    109 |                 />

How can I define this handler correctly?

I have already tried to write the individual points of the error message in the definition of the event handler:

"event: MouseEventHandler<MouseEvent, Event>"

Then the error message disappears in the render area but the following new error message appears:

"Generic type 'MouseEventHandler' requires between 0 and 1 type arguments.ts(2707)"

Here is my Code: (Parents)

interface TodoTableProps {
    mockTodos: Array<Todos>
}



let currentTodos: Todos  [];  

export const TodoTable: FunctionComponent<TodoTableProps> = ({ mockTodos }): ReactElement => {
    //Data input
    if(mockTodos){
        currentTodos = mockTodos;
    }
   
    const [todos, setTodos] = useState<Array<Todos>>(currentTodos);   
    const [enterTodo, setEnterTodo] = useState<string>('');


    //Enter Todo handler
    const handleEnterTodo = (event: any) => {
      setEnterTodo(event.target.value);
    };
  

    //Clear Todo handler
    const handleClearTodos = (event: MouseEventHandler) => {
        const cleanedTodos: Array<Todos> = []
       

        todos.forEach((element: Todos, index: number) => {
            if(todos[index].done == false){

                cleanedTodos.push(todos[index]);
            }
        });
       
        setTodos(cleanedTodos);
        
    }
    

    //Create Todo handler
    const handleCreateTodo = (event: MouseEventHandler<MouseEvent>) => {

        //create new Todo
        const newTodo = {
            //id: todos.length+1,
            id: v4(),
            describtion: enterTodo,
            done: false
        };
     
        setTodos((todos: Array<Todos>) => 
            [
                newTodo,
                ...todos
            ]
        );
        setEnterTodo('');
        
        
    };

    //Delete Todod handler
    const handleDeleteTodo = (event: MouseEvent) => {
        
        const newTodos = [...todos];
        newTodos.splice(todos.indexOf(event), 1);
        
        setTodos(newTodos);   
    }

    //Status handler
    const handleStatus = (event: any) => {
        
        const newStatus = event.done == true ? false : true;
        const newTodos = [ ...todos];
       
        newTodos.forEach((element, index) => {
            if(newTodos[index].id == event.id){
                newTodos[index].done = newStatus;                
            }
        });
        
        setTodos(newTodos);
    }
  
  
    return(
            <>
                <InputBar 
                    enterTodo={ enterTodo } 
                    handleEnterTodo={ handleEnterTodo } 
                    handleCreateTodo={ handleCreateTodo }
                    handleClearTodos= { handleClearTodos }
                />
                
                <TodosDisplay 
                    todos={ todos } 
                    handleDeleteTodo={ handleDeleteTodo } 
                    handleStatus={ handleStatus }
                /> 
            </>      
    );
}

(Child Component)

interface InputBarProps {
    enterTodo: string,
    handleEnterTodo: ChangeEvent<HandleEnterTodo>,
    handleCreateTodo: MouseEventHandler,
    handleClearTodos: any
}

export const InputBar: FunctionComponent<InputBarProps> = ({ enterTodo, handleEnterTodo, handleCreateTodo, handleClearTodos}): ReactElement => {
    return(
          <>
            <form>
              <TextField value={ enterTodo } onChange={ handleEnterTodo }/>
              <Button lable= 'ADD'  disabled= { enterTodo == '' } onClick= { handleCreateTodo } />
              <Button lable= 'CLEAR' disabled= { false } onClick= { handleClearTodos } />
            </form>
          </>
    );
}
3
  • Why dont you set handleClearTodos: MouseEventHandler in child component? Commented Mar 22, 2022 at 14:13
  • Is your problem about event Type ? Commented Mar 23, 2022 at 13:26
  • I just fixed it. Thank you for your help. The problem was I hade an event argument in my function of the handler. Commented Mar 23, 2022 at 15:06

1 Answer 1

3

you can follow as below:

import React, {MouseEvent} from 'react';

const Counter: React.FC = () => {
const clickHandler = (
   // When passing a union as a type parameter,
   // you can provide type-safety to a more
   // abstract handlers:
   e: MouseEvent<HTMLButtonElement | HTMLAnchorElement>
   ): void => {
      e.preventDefault();
      // your code
   }

   return (
     <>
       <button onClick={clickHandler}>Click me!</button>
       <a href="/other-page" onClick={clickHandler}>
        Or click me instead!
       </a>
     </>
  );
 }

If you need to create your own event with additional fields you can extend it from MouseEvent:

 import React, {MouseEvent} from 'react'

 interface CustomEvent extends MouseEvent<HTMLElement> {
    someAdditionalField: number
 }
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.