P4nd4b0b3r1n0
P4nd4b0b3r1n0

Reputation: 2401

How to handle click events on divs with React and Typescript

I have a custom Card component, which gets an "onClick" type, to handle clicking like so:

import React from 'react';
import styles from './card.module.css';

interface Card {
    onClick: React.MouseEventHandler<HTMLDivElement>;
}

const Card: React.FC<Card> = ({ children }) => {
    return <div className={styles.card}>{children}</div>;
};

export default Card;

I'm using Card to compose another component called PostCard like so:

import React from 'react';
import Card from '../Card';
import styles from './postcard.module.css';
import { useRouter } from 'next/router';

type PostCard = {
    title: string;
    description: string;
    slug: string;
};

const PostCard: React.FC<PostCard> = ({ title, description, slug }) => {
    const router = useRouter();

    const handleClick: React.MouseEventHandler<HTMLDivElement> = (e) => {
        console.log('here');
        e.preventDefault();
        router.push('/blog/[slug]', `/blog/${slug}`, { slug });
    };
    return (
        <Card onClick={handleClick}>
            <h2 className={styles.title}>{title}</h2>
            <p className={styles.paragraph}>{description}</p>
        </Card>
    );
};

export default PostCard;

When PostCard is clicked, I want it to use the router function from next.js and push the page to a new page. How ever, when I click on PostCard nothing happens. What's going on? Nothing is printed to the console from handleClick so I'm pretty sure the click isn't being registered by the Card component. Should I be passing the onClick function to the Card component?

Upvotes: 2

Views: 25351

Answers (2)

Ramesh Reddy
Ramesh Reddy

Reputation: 10662

You're using onClick on the Card but the Card returns a div with the children and the onClick prop is not used anywhere.

Try this:

<Card clicked={handleClick}>
    <h2 className={styles.title}>{title}</h2>
    <p className={styles.paragraph}>{description}</p>
</Card>


const Card: React.FC<Card> = ({ children, clicked }) => {
    return <div onClick={clicked} className={styles.card}>{children}</div>;
};

The interface should also be changed:

interface Card {
    clicked: React.MouseEventHandler<HTMLDivElement>;
}

Upvotes: 3

Abito Prakash
Abito Prakash

Reputation: 4770

The onClick needs to be on the div tag instead on Card, here you are sending the handleClick function as a prop to the Card component (onClick), so you need to accept that prop in the Card component and put the function on onClick of the div rendered.

In PostCard

return (
        <Card handleClick={handleClick}>
            <h2 className={styles.title}>{title}</h2>
            <p className={styles.paragraph}>{description}</p>
        </Card>
    );

We can send prop as handleClick instead of onClick to avoid confusion.

And in the Card component

const Card: React.FC<Card> = ({ children, handleClick }) => {
    return <div onClick={handleClick} className={styles.card}>{children}</div>;
};

Upvotes: 4

Related Questions