Issue
I am using selectionStart and selectionEnd in order to get the starting and ending point of a text selection.
Code: https://codesandbox.io/s/busy-gareth-mr04o
However, I am struggling to defined the type of the event on which they can be called on.
If I use any, the code works properly but I would prefer to know the right event.
I tried with these types:
Element
React.SyntheticEvent<HTMLDivElement>
<HTMLDivElement>
with no luck
export default function App() {
const [startText, setStartText] = useState<number | undefined>();
const [endText, setEndText] = useState<number | undefined>();
const handleOnSelect = (event: any) => { <--- I CANNOT FIND THE RIGHT EVENT TYPE
setStartText(event.target.selectionStart);
setEndText(event.target.selectionEnd);
};
return (
<Grid container direction="column" className="App">
You can type here below:
<TextField
value={"This is a example, select a word from this string"}
onSelect={(event) => handleOnSelect(event)}
/>
<br />
<Grid item>The selected word starts at character: {startText}</Grid>
<Grid item>The selected word ends at character: {endText}</Grid>
</Grid>
);
}
Solution
This is a tricky one because the material-ui TextField component involves multiple nested nodes. The argument that is passed to the onSelect function is a div. However the event itself occurs on an input inside the div.
const handleOnSelect = (event: React.SyntheticEvent<HTMLDivElement, Event>) => {
console.log(event.target, event.currentTarget);
};
This logs the input and then the div.
Using event.currentTarget gets very specific Typescript information. We know that it is an HTMLDivElement. But the div doesn't have the properties selectionStart and selectionEnd that we want to access. Those exist on the input.
event.target gives us a very vague type for an EventTarget. We don't know that the target is an input.
One option is to verify the element at runtime.
const handleOnSelect = (event: React.SyntheticEvent<HTMLDivElement, Event>) => {
if ( event.target instanceof HTMLInputElement ) {
setStartText(event.target.selectionStart);
setEndText(event.target.selectionEnd);
}
};
Since you know that the event will always occur on an HTMLInputElement, I think it's safe to make an assertion.
const handleOnSelect = (event: React.SyntheticEvent<HTMLDivElement, Event>) => {
const target = event.target as HTMLInputElement;
setStartText(target.selectionStart);
setEndText(target.selectionEnd);
};
Note that selectionStart and selectionEnd properties use null instead of undefined. So you'll want to either change your state type to <number | null> or replace null with undefined by using null coalescing event.target.selectionStart ?? undefined.
Answered By - Linda Paiste
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.