在 React 中使用按键事件构建 Slack 风格的 Emoji 时获取`:` 后的文本?

Get text after `:` while using keypress event to build Slack-style Emoji in React?

我想创建在您开始使用时显示的 Slack 风格的表情符号 :

我创建了 Stackblitz 复制品 -> https://stackblitz.com/edit/react-ts-uucibv?file=index.tsx

这是我所做的:

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'));

我创建了一个简单的 textarea 来检测按键。我检测到何时按下 : 但我很困惑如何在 :

之后获得所有内容

我正在使用 https://www.npmjs.com/package/emoji-set

当我按下 : 时,我正在调用 ES.getKeywords,但我需要一些方法来获取关键字后的所有内容。例如,如果我写 :c,那么我应该返回 cacabbagecactus 以及从 c 开始的所有其他关键字。但是,:之后我无法完美地获得所有内容。

我希望表情符号选择器既快速又高效,并在此处显示输入的表情符号。

目前,当我搜索 : 时,每个表情符号都会返回,因为字符串为空。

我该怎么做?

有几件事必须改变。首先,您假设每个按键应该控制您的表情符号状态是关闭的,因为 :c 在您的示例中需要两次按键。第一个设置表情符号状态,然后第二个立即清除它导致问题。其次,您的依赖项表示正确的调用方法是 searchByKeyword 而不是 getKeywords.

在我的代码中,我假设当您编辑表情符号并按 space 时,表情符号处理将停止。但基本上,您必须将单次按键触发检查更改为在满足 : 条件时进行检查的切换。

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'));

Modified stackbliz