Home > Back-end >  How to add symbols or characters between each react element?
How to add symbols or characters between each react element?

Time:12-07

I am designing a reusable component for breadcrumbs and I am using compound components pattern. I need to insert symbols between each breadcrumb name like how we would do for array elements and use join method but I am not sure how to do that with react elements.

import React from "react";

const BreadcrumbsItem = ({ children }) => (
  <p>
    {children}
  </p>
);

const Breadcrumbs = ({ children }) => <FlexContainer>{children}</FlexContainer>;

Breadcrumbs.Item = BreadcrumbsItem;

export default Breadcrumbs;

Input:

<Breadcrumbs>
  <Breadcrumbs.Item>Home</Breadcrumbs.Item>
  <Breadcrumbs.Item>Library</Breadcrumbs.Item>
  <Breadcrumbs.Item>Data</Breadcrumbs.Item>
</Breadcrumbs>

Output:

enter image description here

CodePudding user response:

Two solutions for you:

  1. Using CSS

  2. Returning fragments

  3. Using inserted content

Using CSS

Assuming this is for the browser and you want the same delimiter (or one of a small set of them), I'd do it with CSS:

.breadcrumb-item   .breadcrumb-item::before {
    content: " / ";
}

That says "On a .breadcrumb-item that immediately follows another .breadcrumb-item (using the next sibling combinator, , use / as the "before" pseudo-element text (using the ::before pseudo-class and content).

Example:

Show code snippet

.breadcrumb-item   .breadcrumb-item::before {
    content: " / ";
}
<span class="breadcrumb-item">A</span>
<span class="breadcrumb-item">B</span>
<span class="breadcrumb-item">C</span>
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

You could use additional classes to choose among delimiters, or even make the content dependent on an attribute:

Example:

Show code snippet

.breadcrumb-item   .breadcrumb-item::before {
    content: attr(data-before);
}
<span class="breadcrumb-item">A</span>
<span class="breadcrumb-item" data-before="*">B</span>
<span class="breadcrumb-item" data-before="/">C</span>
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

Returning fragments

Your Breadcrumb.Item element could return a fragment when it needs to have a delimiter in front of it:

const content = /*...the rendering of the breadcrumb...*/;
if (delimiter) {
    return <>{delimiter}{content}</>;
}
return content;

Using inserted content

In the Breadcrumbs component, you can convert the children property to an array via React.Children.toArray:

const childArray = React.Children.toArray(children);

Then you can insert what you like between them, perhaps with flatMap:

return <div>{childArray.flatMap((crumb, index) => index === 0 ? crumb : [" / ", crumb])}</div>;

You'll need to add keys to those, though (and not using index unless you know the details of why that's usually not a good idea. How you add the keys and the values you use for them are highly specific to your code, so I'll leave that as an exercise for the reader. :-)

CodePudding user response:

You can use React.Children.forEach in your Breadcrumbs component. Something like this:

let Test = (props) => {
  let result = [];
  React.Children.forEach(props.children, (child, i) => {
    result.push(child);
    i !== React.Children.count(props.children) - 1 && result.push('/');  
  });

  return <div>{result}</div>;
};

export default function App() {
  return (
    <div>
      <Test>
        <div>Hi</div>
        <div>Nice to meet</div>
        <div>you</div>
      </Test>
    </div>
  );
}

demo

  • Related