Change color of specific words if they appear in the editor

Viewed 387

I have a slate text editor. I have a separate component which is divs mapped by an array of predefined words. That section is keywords to use. I want to be able to change the color of words in keywords to use sections to a different color if they exist in the editor.

The way I was thinking about this was I could store the words that I will be writing in the editor in a state which will keep updating if something new is written. And I already have an array of words. I have to somehow find a way to communicate between these two arrays.

How do I approach this?

Code Sandbox

1 Answers

I made this method, is not the better one but (if I understand the problem) could be useful.

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

It will find if the keyword exist in the Editor's data, and you can change the color in your inline css as this:

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

This is the full App.js File with the modification.

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;
Related