如果特定单词出现在编辑器中,则更改它们的颜色

Change color of specific words if they appear in the editor

我有一个平板文本编辑器。我有一个单独的组件,它是由一组预定义单词映射的 div。该部分是要使用的关键字。我希望能够将关键字中的单词颜色更改为使用不同颜色的部分(如果它们存在于编辑器中)。

我当时的想法是,我可以将我将要写的文字存储在编辑器中,如果有新内容出现,该状态会不断更新。我已经有了一系列的单词。我必须以某种方式找到一种在这两个数组之间进行通信的方法。

我该如何处理?

Code Sandbox

我做了这个方法,不是更好的方法,但(如果我理解问题的话)可能会有用。

const isKeyword = (word) => {
    if (value) {
      return value.some(editorObject => {
        return !!editorObject['children'].some(children => 
          children['text'].includes(word))
        })
    }
    return false; 
  }

它会查找关键字是否存在于编辑器的数据中,并且您可以在行内 css 中更改颜色,如下所示:

color: isKeyword(word) ? YOUR_COLOR: 'white'

这是经过修改的完整 App.js 文件。

import React, {useMemo, useState,useEffect} from "react"
import './App.css';
import { createEditor ,Node} from "slate"
import { Slate, Editable, withReact } from "slate-react"
import { IconContext } from "react-icons";
 
import { ImUndo,ImRedo } from "react-icons/im";
import {MdFormatListBulleted, MdFormatItalic,MdFormatBold,MdRedo,MdFormatUnderlined} from "react-icons/md"


function App() {
  const initialState = [{type: 'paragraph', children: [{ text: "edit me"}]}]
  const editor = useMemo( () => withReact(createEditor()), [])
  const [value, setValue] = useState(initialState);
  const [editorValue,setEditorValue] = useState();
  const [wordCount,setWordCount] = useState(0);
   const [color,setColor] = useState(false);

  const [show, setShow] = useState(false);

  const handleClose = () => setShow(false);
  const handleShow = () => setShow(true);

  useEffect(()=>{
    setEditorValue(value.map(n => Node.string(n)).join('\n'));
  },[value]);

  useEffect(() => {
    setWordCount(editorValue && editorValue.trim().split(/\s+/).length);
  },[editorValue]);
  
  console.log(editorValue);
  const wordArray = ['never','forget','to','empty','your','vacuum','bags','never','forget','to','empty','your','vacuum','bags'];

  function keywords(){
    console.log(value.[0].children.[0].text);
    setColor(true);
  }

  useEffect(() => {
     keywords();
  }, [ ])
  const tips = () => {
    return (
      <div>
        Words with emotions in your headlines/subheadline improves SEO. Check this.
      </div>
    )
  }

  const isKeyword = (word) => {
    if (value) {
      return value.some(editorObject => {
        return !!editorObject['children'].some(children => children['text'].includes(word))
      })
    }
    return false; 
  }
  return (
    <div className="container">
          <div>
            <div class="header">
                <div class="header-left" style={{margin:'5px'}}>
                  <IconContext.Provider value={{ color: '#717170', size: '10px' }}>
                  <MdFormatBold style={{padding:'10px'}}/>
                  <MdFormatItalic  style={{padding:'10px'}}/>
                  <MdFormatUnderlined style={{padding:'10px'}}/>
                   <ImUndo style={{padding:'10px'}}/>
                  <ImRedo style={{padding:'10px'}}/>
                  <MdFormatListBulleted style={{padding:'10px'}}/>

                  </IconContext.Provider>
                </div>
               
            </div>
            <div style={{margin:'20px'}}>
            <Slate editor={editor} value={value} onChange={newVal => setValue(newVal)}>
              <Editable />
            </Slate>
            </div>
          </div>
          <div className="sidebar" style={{padding:'20px',
                overflow:'scroll',height:'900px'}}> 
              <div className="Performance"> 
                <h2 className="sidebar-heading"> Performance</h2>
                <div>
                    <div style={{border:'1px solid gray',borderRadius:'5px',fontSize:'15px',padding:'5px',width:'70%',overflow:'hidden'}}>
                    <div style={{float: 'left',paddingRight:'50px'}}>
                      <div className='performance-headings'>Power Words</div>
                      <div>2/6</div>
                    </div>
                    <div><img src="https://img.icons8.com/ios/50/000000/info--v1.png" style={{height:'20px',width:'20px',float:'right'}} onMouseEnter={tips}/></div>
                    </div>
                  
                  <div style={{border:'1px solid gray',fontSize:'15px',padding:'5px',width:'70%',overflow:'hidden'}}>
                      <div style={{float: 'left'}}>
                        <div className='performance-headings'>Readability</div>
                      <div>Fairly Complex to React</div>
                      </div>
                      <div><img src="https://img.icons8.com/ios/50/000000/info--v1.png" style={{height:'20px',width:'20px',float:'right'}} onMouseEnter={tips}/></div>
                  </div>
                  <div style={{border:'1px solid gray',borderRadius:'5px',fontSize:'15px',padding:'5px',width:'70%',boxShadow: '1px 1px #888888'}}>
                  <div className='performance-headings'>Words Count</div>
                    <div>{wordCount}</div>

                    </div>
                </div>
              </div>
              <div className="Addons">
               <h2 className="sidebar-heading"> Addons</h2>
              <div style={{border:'1px solid gray',borderRadius:'5px',padding:'10px',width:'70%',  boxShadow: '2px 2px #888888'}}>
                <button style={{backgroundColor:'#612EEA',color:'white',borderRadius:'5px',border:'0px',fontSize:'20px',padding:'10px'}}>Fact Check</button>   
              </div>
              </div>
              <div className="keywordstouse">
              <h2 className="sidebar-heading"> keywords to use</h2>
 
              {wordArray.map((word,index) => (
              <div style={{borderRadius:'7px',backgroundColor: 'red', padding:'10px',width:'fit-content',textAlign:'center',margin:'5px',color: isKeyword(word) ? 'blue': 'white'}} key ={{index}}>
                {word} 
              </div>))
              }
              </div>
          </div>
  
      
    </div>
  );
}

export default App;