This is a problem I am trying to solve for days. I am using React with TypeScript and Styled Components.
I am trying to port a minesweeper game I originally made in p5js. I am trying to figure out how to add event listeners to the cells. It have been a huge mess, thus before sharing my code (if needed), I would like to ask how this can be done.
I have any array of cell objects in my state (cells). Each cell is a StyledCell component. No matter what I've tried I couldn't attach an onClick property. I have seen every possible error.
Can someone please show me how it can be done?
I am here for any additional information you need.
Edit: After simplifying my code in order to make it easier to follow I will share one of the problematic parts:
import React from "react";
import styled from "styled-components";
import { WON, LOST, EMPTY, MINE, DETONATION, FLAG, DIGITS } from "../../emojis";
interface CellProps extends React.HTMLAttributes<HTMLElement> {
num: number;
i: number;
j: number;
mine: boolean;
minesAround: number;
revealed: boolean;
clicked: boolean;
flagged: boolean;
won: boolean;
lost: boolean;
size: string;
// revealCell: (num: number) => Array<CellType>;
// onClick: React.MouseEventHandler<HTMLButtonElement>;
revealCell: (e: React.MouseEvent<HTMLButtonElement>) => void;
// revealCell: (num: number) => void;
}
const StyledCell = styled.div<CellProps>`
width: 38px;
height: 38px;
line-height: 38px;
font-size: 38px;
margin: 1px;
padding: 0;
text-align: center;
display: flex;
justify-content: center;
align-items: center;
`;
export const Cell: React.FC<CellProps> = ({
num,
mine,
minesAround,
revealed,
clicked,
flagged,
won,
lost,
size,
revealCell,
}) => {
function render() {
if (revealed && clicked && mine) {
return DETONATION;
//
}
if (revealed && mine) {
return MINE;
}
if (revealed) {
// If won, empty cells show the happy face
if (won && minesAround === 0) {
return WON;
// If lost, empty cells show the sad face
} else if (lost && minesAround === 0) {
return LOST;
}
// Calculate the number of mines around and draw that
return DIGITS[minesAround];
}
if (flagged) {
return FLAG;
}
return EMPTY;
}
return <StyledCell onClick={revealCell}>{render()}</StyledCell>;
};
In the line:
return <StyledCell onClick={revealCell}>{render()}</StyledCell>;
onClick is marked as an error and the error message I get is this:
(property) onClick?: (React.MouseEventHandler & React.MouseEventHandler) | undefined No overload matches this call. Overload 1 of 2, '(props: { i: number; slot?: string | undefined; style?: CSSProperties | undefined; title?: string | undefined; ref?: ((instance: HTMLDivElement | null) => void) | RefObject<...> | null | undefined; ... 262 more ...; revealCell: (e: MouseEvent<...>) => void; } & { ...; } & { ...; }): ReactElement<...>', gave the following error. Type '(e: MouseEvent<HTMLButtonElement, MouseEvent>) => void' is not assignable to type 'MouseEventHandler & MouseEventHandler'. Type '(e: MouseEvent<HTMLButtonElement, MouseEvent>) => void' is not assignable to type 'MouseEventHandler'. Types of parameters 'e' and 'event' are incompatible. Type 'MouseEvent<HTMLDivElement, MouseEvent>' is not assignable to type 'MouseEvent<HTMLButtonElement, MouseEvent>'. Type 'HTMLDivElement' is missing the following properties from type 'HTMLButtonElement': disabled, form, formAction, formEnctype, and 13 more. Overload 2 of 2, '(props: StyledComponentPropsWithAs<"div", any, CellProps, never, "div", "div">): ReactElement<StyledComponentPropsWithAs<"div", any, CellProps, never, "div", "div">, string | JSXElementConstructor<...>>', gave the following error. Type '(e: MouseEvent<HTMLButtonElement, MouseEvent>) => void' is not assignable to type 'MouseEventHandler & MouseEventHandler'.ts(2769) index.d.ts(1479, 9): The expected type comes from property 'onClick' which is declared here on type 'IntrinsicAttributes & { i: number; slot?: string | undefined; style?: CSSProperties | undefined; title?: string | undefined; ref?: ((instance: HTMLDivElement | null) => void) | RefObject<...> | null | undefined; ... 262 more ...; revealCell: (e: MouseEvent<...>) => void; } & { ...; } & { ...; }' index.d.ts(1479, 9): The expected type comes from property 'onClick' which is declared here on type 'IntrinsicAttributes & { i: number; slot?: string | undefined; style?: CSSProperties | undefined; title?: string | undefined; ref?: ((instance: HTMLDivElement | null) => void) | RefObject<...> | null | undefined; ... 262 more ...; revealCell: (e: MouseEvent<...>) => void; } & { ...; } & { ...; }'
I have tried any possible solution I could think of.