0

I wrote this component for text highlighting:

import { FC } from 'react'
import './Highlight.css'

interface HighlightProps {
    filter: string
    str: string 
}

const Highlight: FC<HighlightProps> = ({filter, str}) =>{

    if (!filter) return str

    const regexp = new RegExp(filter, 'ig')
    const matchValue = str.match(regexp)

    if (matchValue) {
        return str.split(regexp).map((s: string, index: number, array: string[]) => {
            if (index < array.length - 1) {
                const overlap = matchValue.shift()
                return (
                    <span key={index}>
                        {s}<span className='highlight'>{overlap}</span>
                    </span>
                )
            }
            return s
        })
    }
    return str
}

export default Highlight

It takes filter: string and str: string props. Everything working just fine but if I leave everything as it is above I keep getting this error:

Type '({ filter, str }: HighlightProps) => string | (string | Element)[]' is not assignable to type 'FC<HighlightProps>'.
  Type 'string | (string | Element)[]' is not assignable to type 'ReactElement<any, any> | null'.
    Type 'string' is not assignable to type 'ReactElement<any, any>'.ts(2322)

My question is - how can I properly make typisation for this component and its props?

P.S. I've tried to put s and str values in return statements into <>{..}</> but it did not help.

1 Answer 1

1

You have to ensure you are returning proper JSX in all cases.
Now react expects to return a single wrapping Element Node inside which you can have your children. Inside the second if statement, you are returning multiple <span> elements but without a parent. Just wrap the bit with Fragments too :

import { FC } from "react";
import "./Highlight.css";

type HighlightProps = {
  filter: string;
  str: string;
};

const Highlight: React.FC<HighlightProps> = ({ filter, str }) => {
  if (!filter) return <>str</>;

  const regexp = new RegExp(filter, "ig");
  const matchValue = str.match(regexp);

  if (matchValue) {
    return (
      <>
        {str.split(regexp).map((s: string, index: number, array: string[]) => {
          if (index < array.length - 1) {
            const overlap = matchValue.shift();
            return (
              <span key={index}>
                {s}
                <span className="highlight">{overlap}</span>
              </span>
            );
          }
          return s;
        })}
      </>
    );
  }
  return <>str</>;
};

export default Highlight;

Sandbox

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.