3

Hello I am new to typescript and I have job to do here. I need to make dynamic class, something like in this code bellow.

import React, { ReactNode, useState } from "react";

interface Props {
  text: ReactNode;
}

const ListItem = ({ text }: Props) => {
    let [showMore, setShowMore] = useState(false);

    return (
        <div className="item">
            <div>
                <div className={`text ${showMore ? "active" : ""}`}>{text}</div>
            </div>
            <button onClick={() => setShowMore((s) => !s)}>Show more</button>
        </div>
    );
};

But I need to implement it to this code and I have no idea how to do it, because I don't understand this syntax from someone who wrote it. When I try to implement previous code, I have problem with react hooks rendering in this syntax.

I hope you understand my problem

type DeliveryBranchHitProps = {
  hit: SearchIndex.DeliveryBranch;
};
const DeliveryBranchHit = ({
  hit: delivery_branch,
}: DeliveryBranchHitProps): JSX.Element => (
  <>
      <div className={`branch-opening-week ${showMore ? "active" : ""}`}>
        <p>
          <span className="branch-day">Monday:</span>
          {delivery_branch.opening_monday}
        </p>
        <button onClick={() => setShowMore((s) => !s)}>Show more</button>

    </div>
  </>
);
Peloucvo
  • 219
  • 1
  • 10
  • What do you mean by 'I have problem with react hooks rendering in this syntax' , can you show us with some example? – HDM91 Dec 19 '21 at 16:55
  • It gives me invalid hook call error: invalid hook call. hooks can only be called inside of the body of a function component. – Peloucvo Dec 19 '21 at 17:07

2 Answers2

2

Not quite sure I understand your question, but possibly you want to do something like this where you have a generic component that takes some content chilren.


interface Props {
  text: ReactNode;
  children: ReactNode;
}

const ListItem = ({ text, children }: Props) => {
  let [showMore, setShowMore] = useState(false);

  return (
    <div className="item">
      <div>
        <div className={`text ${showMore ? "active" : ""}`}>
          {text}
          {children}
        </div>

        <button onClick={() => setShowMore((s) => !s)}>Show more</button>
      </div>
    </div>
  );
};

type DeliveryBranchHitProps = {
  hit: SearchIndex.DeliveryBranch;
};

const DeliveryBranchHit = ({ hit: delivery_branch }: DeliveryBranchHitProps): JSX.Element => (
  <>
    <ListItem text={delivery_branch.name} />
      <p>
        <span className="branch-day">Monday:</span>
        {delivery_branch.opening_monday}
      </p>
    </ListItem>
  </>
);
Ayman El Temsahi
  • 2,600
  • 2
  • 17
  • 27
1

Please check this post to understand const func = () => ( .. ) syntax Arrow function without curly braces

For now your function returns a single expression - i.e. some JSX. To add some additional logic you need to make your function multiline (pay attention to the braces):

const Func = (props) => {
  // your hook goes here
  let [state, useState] = useState();

  // return the jsx
  return ( .. )
}

UPD: so for your case it is:

type DeliveryBranchHitProps = {
  hit: SearchIndex.DeliveryBranch;
};
const DeliveryBranchHit = ({
  hit: delivery_branch,
}: DeliveryBranchHitProps): JSX.Element => {
 let [showMore, setShowMore] = useState(false);

return (
  <>
      <div className={`branch-opening-week ${showMore ? "active" : ""}`}>
        <p>
          <span className="branch-day">Monday:</span>
          {delivery_branch.opening_monday}
        </p>
        <button onClick={() => setShowMore((s) => !s)}>Show more</button>

    </div>
  </>
);

}
alex-panin
  • 49
  • 3
  • Thank you, I understand functional component's syntax, but I dont understand this jsx element syntax. Dont you know how to redo it to functional component? – Peloucvo Dec 19 '21 at 17:12
  • your component is a totally valid functional one. What you need to do is to add hook to it. In order to do so, you need to convert your function ('component') from one-liner to a regular multiline. – alex-panin Dec 19 '21 at 17:19