Home > other >  React typescript handle JSX.Element or string
React typescript handle JSX.Element or string

Time:07-28

I have a payload that looks like this :

{
  age: 35,
  comments: "Walk in appointments",
  dateTime: {
  content: {
    $$typeof: Symbol(react.element),
    key: null,
    props: {
      children: "30-Aug-2021, 03:35 PM",
      className: "-esm-appointments__appointments-table__statusContainer___RFuGX"
    },
    ref: null,
    type: "span",
  },
  dob: "03 — Apr — 1986",
  gender: "M",
  id: "7cd38a6d-377e-491b-8284-b04cf8b8c6d8",
  location: "HIV Clinic",
  name: {
    content: {
    $$typeof: Symbol(react.element),
    key: null,
    props: {
    children: "John Wilson",
    to: "${openmrsSpaBase}/patient/8673ee4f-e2ab-4077-ba55-4980f408773e/chart"
  },
  ref: null,
  type: ƒ ConfigurableLink(_param),
  _self: null,
  patientUuid: "8673ee4f-e2ab-4077-ba55-4980f408773e",
  phoneNumber: "0700000000",
  provider: "Dr James Cook",
  visitType: "HIV Clinic"
}

It contains data from table rows , which are formatted like this :

const tableRows = useMemo(() => {
    return appointments?.map((appointment) => ({
      ...appointment,
      name: {
        content: (
          <ConfigurableLink to={`\${openmrsSpaBase}/patient/${appointment.patientUuid}/chart`}>
            {appointment.name}
          </ConfigurableLink>
        ),
      },
  }, [appointments]);

I am trying to create an interface for appointments data, which should handle data from different sources, some are JSX elements and some are strings.

I am having a hard time creating an interface that can handle either a JSX.Element or string :

export interface MappedAppointment {
  id: string;
  name: { content: JSX.Element } | string;
  age: string;
  gender: string;
  phoneNumber: string;
  dob: string;
  patientUuid: string;
  dateTime: { content: JSX.Element } | string;
  serviceType: { content: JSX.Element } | string;
}

I keep getting the error Property 'content' does not exist on type 'string | { content: Element; }'.Property 'content' does not exist on type 'string'. . This is my view :

<span className={styles.label}>{appointment.name.content.props.children}</span> <br></br>

Any advise will be appreciated. Thanks

CodePudding user response:

You can check the typeof of name property before accessing the property of it. If is not string type then access the content property on it.

typeof appointment.name === "string" ? appointment.name : appointment.name.content.props.children

Full code:

<span className={styles.label}>
    {typeof appointment.name === "string" ? appointment.name : appointment.name.content.props.children}
</span> 
<br></br>

You can read about type guarding using various patterns at this Typescript documentation.

CodePudding user response:

Similar to the previous answer. You can try an Elvis operator and check that the property exists.

Like:

<span className={styles.label}>
{(appointment.name.content && appointment.name.content.props && appointment.name.content.props.children) ? 
  appointment.name.content.props.children :
  appointment.name
}
</span> 
<br></br>

CodePudding user response:

name.content is an object, not a JSX element. What you mean to type is

name: {
  content: {
    $$typeof: JSX.Element | string;
    ...other properties
  }
};

That said, this response data looks tricky to me due to object keys/value such as type: ƒ ConfigurableLink(_param), _self and $$typeof. I'd recommend not using such keys as javascript may have issues reading them.

  • Related