Company logo
  • Jobs
  • Bootcamp
  • About Us
  • For professionals
    • Home
    • Jobs
    • Courses
    • Questions
    • Teachers
    • Bootcamp
  • For business
    • Home
    • Our process
    • Plans
    • Assessments
    • Payroll
    • Blog
    • Sales
    • Calculator

0

58
Views
How to get Tag component to know that it is wrapped under Tag Group component without using props?

So I have two components: Tag and TagGroup. When Tag component is used alone, I want that component to use <div> tag and when Tag is wrapped inside of TagGroup, which means more than 1 Tag is being used, then I want it to use <li> tag. With my current design, I used context to pass prop groupUpTags to Tag component. When groupUpTags is true then Tag component will use <li> tag, if false, <div> will be used. Currently, it doesn't even work properly as whether I wrap Tag component under TagGroup or not <li> tag is always being used. My question is, is there a way to get Tag component to render <li> tag when wrapped inside TagGroup without using any props and render <div> tag when used alone? My current design look little too messy. https://codesandbox.io/s/tag-group-s07oyh?file=/src/App.tsx

App.tsx

import "./styles.css";
import React from "react";
import { TagGroupContextInterface, TagGroupContext } from "./TagGroupContext";

export interface TagGroupInterface extends TagGroupContextInterface {
  children: React.ReactNode;
}

const Tag = () => {
  const context = React.useContext(TagGroupContext);
  return context.groupUpTags ? (
    <li className="tag">Tag</li>
  ) : (
    <div className="tag">Tag</div>
  );
};

const TagGroup = ({ groupUpTags = true, children }: TagGroupInterface) => {
  const context = React.useMemo(
    () => ({
      groupUpTags
    }),
    [groupUpTags]
  );

  return (
    <TagGroupContext.Provider value={context}>
      <div>
        <ul>{React.Children.map(children, (child) => child)}</ul>
      </div>
    </TagGroupContext.Provider>
  );
};

export default function App() {
  return (
    <div className="App">
      <TagGroup>
        <Tag />
        <Tag />
        <Tag />
      </TagGroup>
    </div>
  );
}

TagGroupContext.tsx

import React from "react";

export interface TagGroupContextInterface {
  groupUpTags?: boolean;
}

const defaultTagGroupContext: TagGroupContextInterface = {
  groupUpTags: true
};

export const TagGroupContext = React.createContext<TagGroupContextInterface>(
  defaultTagGroupContext
);
7 months ago · Juan Pablo Isaza
1 answers
Answer question

0

Keep your components more deterministic

A Tag component should probably always return a simple tag in a div or a span whatever you need for the stand alone tag to work.

I would then add the li inside the list component since thats the moment you need the li. when you code a Tag it shouldn't know about the parents.

Probably something like this in your Tag Group

{Children.map(children, (child, i) => {
  <li key={i}>{child}</li>;
})}

note: don't use "i" as a key its not reliable. Use a uid from the tag itself.

7 months ago · Juan Pablo Isaza Report
Answer question
Find remote jobs