Home > Enterprise >  Problem with functional component typisation
Problem with functional component typisation

Time:06-25

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.

CodePudding user response:

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

  • Related