0

I have a react component that receives an id from its props.

export type MyComponentProps = {
  id: string
}

export const MyComponent = function(props: MyComponentProps) {
  return (
    <div>{props.id}</div>
  );
}

Now, I want to make the id optional, but I do have a requirement to use identifiers so I make the id as optional and add a default prop.

import { v4 } from 'uuid';

export type MyComponentProps = {
  id?: string
}

export const MyComponent = function(props: MyComponentProps) {
  return (
    <div>{props.id}</div>
  );
}

MyComponent.defaultProps = {
  id: `MyComponent-${v4()}`
}

Done! Except, now, if I render 2 different instances of MyComponent they will have the same id. How do I work around this? What I did is the following, but I am no react expert and I don't know if there is another way to accomplish this.

import { v4 } from 'uuid';

export type MyComponentProps = {
  id?: string
}

export const MyComponent = function(props: MyComponentProps) {
  const id = props.id?? `MyComponent-${v4()}`;
  return (
    <div>{id}</div>
  );
}
2
  • One problem with your final implementation, potentially, is that the ID changes every time the component renders. But it's unclear what you actually need the ID for, maybe that's OK. Commented May 5, 2022 at 20:47
  • The id is used for the html component attributes required by bootstrap to... say open an accordion for example. So, due to the nature of UUIDs it won't really make a difference recalculating the ID every time (as long as they are unique), from a performance perspective, and at a larger scale it may cause some impact. So using a state to store that id as stated by @Ben West in the answer below is the way to go. Commented May 9, 2022 at 14:13

2 Answers 2

1

If you want a per-component ID that stays the same between renders, you'll need to put it in state.

export const MyComponent = function(props: MyComponentProps) {
  const [defaultId] = useState(v4)
  const id = props.id ?? defaultId
  return (
    <div>{id}</div>
  );
}
Sign up to request clarification or add additional context in comments.

Comments

0

Technically, cacheing a value is possible using currying by implementing an HOC.

A basic implementation would look like:

import { useRef } from "react";
import { v4 as uuidv4 } from "uuid";

const withId = (Component: React.FC) => ({ children, ...props }) => {
    const id = useRef(uuidv4).current;
    return <Component {...props} id={id} />;
}

const ComponentWithId = withId(Component);

/* Usage */
interface WithId {
    id: string;
}

interface Props extends WithId {}

const Component = ({ id }: Props) => {
    return <div id={id}>Some content</div>;
}

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.