0

I have a method that returns an array of components that can be comletely different:

renderComponents() {
  const children = [];
  children.push(this.renderComponent1());
  children.push(this.renderComponent2());
  if (something) {
    children.push(this.renderComponent3());
  }

  return children;
}

But of course I'm getting an error Each child in an array or iterator should have a unique "key" prop.. I've tried to set key like this:

children.forEach((child, i) => {
  Object.defineProperty(child.props, 'key', { value: i });
});

But as it turns out React prevents extension of props so I've received Cannot define property key, object is not extensible.

So my question is next: is it possible to set key prop to each component in an array after instantiating of those components?

UPD: The real code is next (it renders a pagination with ranges like this [1]...[5][6][7][8][9]...[100]):

  renderPaginationButton(page) {
    const { query, currentPage } = this.props;

    return (
      <Link
        className={classNames(styles.link, { [styles.active]: page === currentPage })}
        to={routes.searchUrl({ ...query, page })}
      >
        {page}
      </Link>
    );
  }

  renderPaginationSeparator() {
    return (
      <div className={styles.separator}>...</div>
    );
  }

  renderPaginationRange(from, amount) {
    const { pagesCount } = this.props;
    const result = [];

    for (let i = Math.max(from, 1); i < Math.min(from + amount, pagesCount); i++) {
      result.push(this.renderPaginationButton(i));
    }

    return result;
  }

  renderPagination() {
    const { currentPage, pagesCount } = this.props;

    if (pagesCount <= 1) {
      return;
    }

    const children = this.renderPaginationRange(currentPage - 2, 5);

    if (currentPage > 4) {
      children.unshift(
        this.renderPaginationButton(1),
        this.renderPaginationSeparator()
      );
    }

    if (pagesCount - currentPage > 4) {
      children.push(
        this.renderPaginationSeparator(),
        this.renderPaginationButton(pagesCount)
      );
    }

    return (
      <div className={styles.pagination}>
        {children}
      </div>
    );
  }
4
  • 1
    I think the real solution is to just set the keys properly on your renderComponent1, 2, and 3. Could you also share the code for those components? Commented Oct 15, 2018 at 21:06
  • "should" is not "must" ... Commented Oct 15, 2018 at 21:10
  • @AndrewSteinheiser added a real code Commented Oct 15, 2018 at 21:11
  • @JonasWilms yes, but it's not a solution to just ignore it. ) Commented Oct 15, 2018 at 21:12

1 Answer 1

1

To answer your question directly, you can use React.cloneElement to add props onto an already instantiated component.

But that's not what you should do in this case.

In your case, you should have renderPaginationButton() to return a <Link> element with key= prop already put in.

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

1 Comment

Yeah, I rethinked an architecture and moved all this logic to a separate component and added key prop to each link explicitly. I just wanted to avoid passing some key argument to renderSeparator method but now it seems not so bad for me. )

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.