I want to create Slack-style emoji that shows up when you start using :
I have created a Stackblitz reproduction -> https://stackblitz.com/edit/react-ts-uucibv?file=index.tsx
Here's what I did:
import React, { Component } from 'react';
import { render } from 'react-dom';
import React from 'react';
import ES from 'emoji-set';
const TextArea = () => {
const [text, setText] = React.useState('');
const [openEmoji, setOpenEmoji] = React.useState(false);
const keyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {
if (e.key === ':') {
setOpenEmoji(true);
} else {
setOpenEmoji(false);
}
};
const textChanged = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
const newText = e.target.value;
if (openEmoji) {
console.log(ES.getKeywords(newText));
}
setText(newText);
};
return (
<div>
<textarea
value={text}
onKeyDown={keyDown}
onChange={textChanged}
placeholder="Type here..."
spellCheck={false}
style={{
width: '350px',
height: '50vh'
}}
/>
</div>
);
};
class App extends Component {
render() {
return (
<div>
<h1>React Slack Emoji</h1>
<TextArea />
</div>
);
}
}
render(<App />, document.getElementById('root'));
I created a simple textarea
that detects keypresses. I detect when :
is pressed but I am confused as to how do I get everything after a :
I am using https://www.npmjs.com/package/emoji-set
I'm calling ES.getKeywords
right when I press :
but I need some way to get everything after keywords. For example, if I write :c
then I should be returned ca
, cabbage
, cactus
& all other keywords starting from c
. However, I am unable to get everything after :
perfectly.
I want the emoji-picker to be fast & performant as well as show the emoji's typed right there.
Currently, I get returned every Emoji when I search :
as the string is empty.
How do I do it?
Couple of things have to change. First, your assumption that each key down should control your emoji state is off because :c
as in your example requires two key presses. The first sets the emoji state, then the second immediately clears it causing a problem. Second, your dependency says that the proper method to call is searchByKeyword
not getKeywords
.
In my code I have an assumption that when you are editing an emoji and press space, the emoji processing gets stopped. But basically you have to change from a single key press triggering checking to be a toggle that checks while the :
condition is met.
import React, { Component } from 'react';
import { render } from 'react-dom';
import React from 'react';
import ES from 'emoji-set';
const TextArea = () => {
const [text, setText] = React.useState('');
const [openEmoji, setOpenEmoji] = React.useState(false);
const keyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {
// changed
if (e.key === ':' && !openEmoji) {
setOpenEmoji(true);
} else if (e.key === ' ' && openEmoji) {
setOpenEmoji(false);
} else if (e.key === ':' && openEmoji) {
setOpenEmoji(false);
}
};
const textChanged = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
const newText = e.target.value;
const emojiToSearch = newText.split(/:/).pop(); // changed
// changed
if (openEmoji && emojiToSearch && emojiToSearch.length > 1) {
console.log(ES.searchByKeyword(emojiToSearch));
}
setText(newText);
};
return (
<div>
<textarea
value={text}
onKeyDown={keyDown}
onChange={textChanged}
placeholder="Type here..."
spellCheck={false}
style={{
width: '350px',
height: '50vh'
}}
/>
</div>
);
};
class App extends Component {
render() {
return (
<div>
<h1>React Slack Emoji</h1>
<TextArea />
</div>
);
}
}
render(<App />, document.getElementById('root'));