Ausnahme gefangen: SSL certificate problem: certificate is not yet valid 📌 Compound components pattern for creating reusable Rating component

🏠 Team IT Security News

TSecurity.de ist eine Online-Plattform, die sich auf die Bereitstellung von Informationen,alle 15 Minuten neuste Nachrichten, Bildungsressourcen und Dienstleistungen rund um das Thema IT-Sicherheit spezialisiert hat.
Ob es sich um aktuelle Nachrichten, Fachartikel, Blogbeiträge, Webinare, Tutorials, oder Tipps & Tricks handelt, TSecurity.de bietet seinen Nutzern einen umfassenden Überblick über die wichtigsten Aspekte der IT-Sicherheit in einer sich ständig verändernden digitalen Welt.

16.12.2023 - TIP: Wer den Cookie Consent Banner akzeptiert, kann z.B. von Englisch nach Deutsch übersetzen, erst Englisch auswählen dann wieder Deutsch!

Google Android Playstore Download Button für Team IT Security



📚 Compound components pattern for creating reusable Rating component


💡 Newskategorie: Programmierung
🔗 Quelle: dev.to

👋 Hey folks

This article will give you an explanation of a "Compound components" pattern.

🤔 Why should I know about the "Compound components"?

"Compound components" is a pattern that helps to create reusable components dependent on each other. Such a pattern helps to achieve better isolation. This approach allows developers to easily create dynamic and interactive user interfaces while keeping the code clean and organized. This is just one of the many benefits of using React and compound components in web development.

👨‍🔬 Could you show me an image explanation?

Rating - component should contain logic for enormous stars and be easily scalable and reusable.

The RatingItem - component should consume the logic from the Rating component and don't contain any styling, to reuse across different projects or designs. Because the UI design can be changed in the future, and your star will become a smile or something else.

Rating component top level explanation

👨‍🔬 Ok, before implementing, let me explain the Rating components deeper!

What should we store in the Rating component?

  • Rating state, in our case, ranges from 1 to 5.
  • Hovered boolean to know if our user hovers over our rating component?
  • Hovered state, from 1 to 5, to create a good UI experience.

What will be inside the RatingItem component?

  • No styling because the design can be different in projects, and it will be a pain to change the RatingItem each time we have a new design.
  • Different handlers, like handleClick or handleMouseLeave, depending on your needs.

Compound Components implementation structure

👨‍💻 Let's code it!

folder structure

contexts/RatingContext.ts
providers/RatingProvider.ts
components/Rating.tsx
components/RatingItem.tsx
components/Feedback.tsx

1) Creating Context and Provider for a Rating component.

contexts/RatingContext.ts

export const RatingContext = createContext({
  rating: 0,
  setRating: (_rating: number) => {},
  hoverRating: 0,
  setHoverRating: (_rating: number) => {},
  isHovering: false,
  setIsHovering: (_isHovering: boolean) => {},
});

providers/RatingProvider.ts

export const RatingProvider = RatingContext.Provider

We're creating Context because we need to pass information from Rating to RatingItem, whatever nesting it will be.

2) Creating a Rating component with the basic state needed.

components/Rating/Rating.tsx

type Props = {
  children: ReactNode
}

export const Rating: FC<Props> = ({ children }) => {
  const [rating, setRating] = useState(0) // used to store the current rating
  const [hoverRating, setHoverRating] = useState(0) // store information about the current hovered state
  const [isHovering, setIsHovering] = useState(false) // information about is the rating hovered right now or not

  const contextValue = useMemo(
    () => ({
      rating,
      hoverRating,
      isHovering,
      setRating,
      setHoverRating,
      setIsHovering,
    }),
    [rating, hoverRating, isHovering],
  )

  return <RatingProvider value={contextValue}>{children}</RatingProvider>
}

3) Let's create a hook to consume the RatingContext

import { useContext } from "react"

import { RatingContext } from "../../contexts/RatingContext"

export const useRatingContext = () => {
  const context = useContext(RatingContext)

  if (!context) {
    throw new Error("useRatingContext must be used within a RatingContext")
  }

  return context
}

📝 Note: Here, we have a "Compound components" logic. The idea is that this hook will throw an error wherever we try to use the component with this hook outside of the Rating.

4) Creating <RatingItem /> component.

components/RatingItem.tsx

type Props = {
  value: number
  children: JSX.Element
}

export const RatingItem = ({ value, children }: Props) => {
  const { setRating, rating, hoverRating, setHoverRating, setIsHovering } = useRatingContext()

  return (
    <span className="cursor-pointer">
      {cloneElement(children, { needed_props_here })}
    </span>
  )
}
  • Prop value is used to pass information about what value of the rating will represent your RatingItem like 1, 2, or 0.5, depending on your needs.
  • useRatingContext gives access to provider values.
  • {cloneElement(children, { neededPropsHere })} will provide to your icon all props that are needed in the future to control this icon UI state. We're using here the cloneElement API.

5) Improving <RatingItem /> component by adding additional handlers.

export const RatingItem = ({ value, children }: Props) => {
  const { setRating, rating, hoverRating, setHoverRating, setIsHovering } = useRatingContext()

  // new code
  const handleMouseEnter = () => {
    setHoverRating(value)
    setIsHovering(true)
  }

  const handleMouseLeave = () => {
    setHoverRating(0)
    setIsHovering(false)
  }

  const handleClick = () => {
    if (rating === value) {
      setRating(0)

      return;
    }

    setRating(value)
  }

  const isCurrentRating = rating === value
  const isHoveredRating = hoverRating === value
  const isRatingNotSet = rating === 0
  const isFilled = isRatingNotSet || isCurrentRating || isHoveredRating

  return (
    <span
      onMouseEnter={handleMouseEnter}
      onMouseLeave={handleMouseLeave}
      onClick={handleClick}
      className="cursor-pointer"
    >
// end of new code
      {cloneElement(children, { isFilled, isChoose: isCurrentRating })}
    </span>
  )
}
  • We added code to handle the mouse events handleClick, handleMouseLeave, and handleMouseEnter.
  • We added constants isCurrentRating, isHoveredRating, isRatingNotSet, and isFilled, which will be used to implement the needed UI pattern. This part can vary depending on your design!

6) We created almost all the needed logic to display our rating.

components/Feedback/feedback.tsx

export const Feedback = () => {
    return (
        <Rating>
            <div className={styles.rating}>
              <RatingItem value={1}>
                <IconVeryBad />
              </RatingItem>
              <RatingItem value={2}>
                <IconBad />
              </RatingItem>
              <RatingItem value={3}>
                <IconNeutral />
              </RatingItem>
              <RatingItem value={4}>
                <IconGood />
              </RatingItem>
              <RatingItem value={5}>
                <IconVeryGood />
              </RatingItem>
            </div>
        </Rating>
    )
}

7) But what if we need to know in the Feedback component what is the rating right now?

components/Rating.tsx

type Props = {
  children: ReactNode
  onRatingChange?: (rating: number) => void // new prop onRatingChange
}

export const Rating: FC<Props> = ({ children, onRatingChange }) => {
  const [rating, setRating] = useState(0)
  const [hoverRating, setHoverRating] = useState(0)
  const [isHovering, setIsHovering] = useState(false)

  const contextValue = useMemo(
    () => ({
      rating,
      hoverRating,
      isHovering,
      setRating,
      setHoverRating,
      setIsHovering,
    }),
    [rating, hoverRating, isHovering],
  )

  useEffect(() => { 
    onRatingChange?.(rating) // a prop function be called each time rating is changing
  }, [rating])

  return <RatingProvider value={contextValue}>{children}</RatingProvider>
}

  • onRatingChange - a function that will be called when the user changes the rating.

8) Usage of the Rating component

component/RatingFeedback.tsx

export const RatingFeedback = () => {
  const [isShowText, setShowText] = useState(false)

  const handleRatingChange = (rating: number) => {
    if (rating > 0) {
      setShowText(true)
      setRating(rating)
    } else {
      setShowText(false)
      setRating(0)
    }
  }

  return (
    <>
      <Rating onRatingChange={handleRatingChange}>
        <div className="flex justify-between w-full pointer-events-auto background-color-300 mt-4 max-w-[300px]">
          <RatingItem value={1}>
            <IconVeryBad />
          </RatingItem>
          <RatingItem value={2}>
            <IconBad />
          </RatingItem>
          <RatingItem value={3}>
            <IconNeutral />
          </RatingItem>
          <RatingItem value={4}>
            <IconGood />
          </RatingItem>
          <RatingItem value={5}>
            <IconVeryGood />
          </RatingItem>
        </div>
      </Rating>
      {isShowText && (
        <label>
            Please write to us
            <textarea/>
        </label>
      )}
    </>
  )
}
  • handleRatingChange is responsible for showing a text field when the user chooses a rating

🏁 Summary

In this article, we demonstrated the use of "Compound components" for creating a rating system using React. Compound components allow you to create complex UI components by combining simple and reusable components. This approach improves code organization, making it easier to maintain and extend. The example we used showed how to create a rating system that is both user-friendly and customizable.

To test the code and see the example in action, you can follow the link: https://codesandbox.io/p/sandbox/compound-components-for-rating-y6getu.

...



📌 Compound components pattern for creating reusable Rating component


📈 107.34 Punkte

📌 React Pattern - Build Better Component with Compound component


📈 60.56 Punkte

📌 How to Build a Dynamic Dropdown Component in React – React Compound Component Pattern Explained


📈 60.56 Punkte

📌 React Components 101: Building Reusable Components


📈 43.97 Punkte

📌 A transição do Higher-Order Component pattern para o React Hooks pattern


📈 39.15 Punkte

📌 Creating a Multicolored Star Rating Card Component


📈 35.28 Punkte

📌 Creating an Interactive Multicolored Star Rating Component


📈 35.28 Punkte

📌 Designing and Evaluating Reusable Components - 2004


📈 32.3 Punkte

📌 Building reusable components in ReactJS


📈 32.3 Punkte

📌 Using the TypeScript generic type to create reusable components


📈 32.3 Punkte

📌 Create reusable button Components with React,Typescript , Tailwind and Tailwind-variants


📈 32.3 Punkte

📌 How to Build Reusable React Components


📈 32.3 Punkte

📌 Writing clean, reusable components in React (best practices)


📈 32.3 Punkte

📌 Writing Clean, Reusable Components in Vue 3 (Composition API): Best Practices


📈 32.3 Punkte

📌 React Design Patterns — Best Practices for Building Scalable and Reusable Components


📈 32.3 Punkte

📌 NinjaBootstrap UI - A Pragmatic Approach To Bootstrap Reusable HTML Components


📈 32.3 Punkte

📌 Reusable component store for pagination using generics


📈 31.04 Punkte

📌 Introducing Shadcn UI: A reusable UI component collection


📈 31.04 Punkte

📌 Reusable Modal Component using React Portals


📈 31.04 Punkte

📌 Creating reusable GitHub Action workflows for Bicep


📈 30.92 Punkte

📌 PHPJabbers Star Rating Script 4.0 Rating Item Stored cross site scripting


📈 29.19 Punkte

📌 PHPJabbers Star Rating Script 4.0 Rating Item Stored Cross Site Scripting


📈 29.19 Punkte

📌 C# Pattern Matching Inside Out: Kompakter und prägnanter C#-Code durch Pattern Matching


📈 28.75 Punkte

📌 Neu in .NET 7 [5]: List Pattern und Slice Pattern mit C# 11


📈 28.75 Punkte

📌 [dos] Pdfium - Out-of-Bounds Read with Shading Pattern Backed by Pattern Colorspace


📈 28.75 Punkte

📌 #0daytoday #Pdfium - Out-of-Bounds Read with Shading Pattern Backed by Pattern Colorspace Exploit [#0day #Exploit]


📈 28.75 Punkte

📌 Observer Pattern: Was steckt hinter dem Observer Design Pattern?


📈 28.75 Punkte

📌 Factory Pattern: Alle Informationen zum Factory Method Pattern


📈 28.75 Punkte

📌 Let’s Learn Some Physics Playing With Compound Pulleys


📈 25.38 Punkte

📌 Let’s Learn Some Physics Playing With Compound Pulleys


📈 25.38 Punkte

📌 Steve Jurvetson: The Compound Effect of Artificial Intelligence & Silicon-Based Technologies


📈 25.38 Punkte

📌 Spread of Breast Cancer Linked To Compound In Asparagus and Other Foods


📈 25.38 Punkte

📌 Quick Analysis of an Encrypted Compound Document Format, (Fri, Feb 21st)


📈 25.38 Punkte

📌 Hancom Office 2010/Office 2014/Office 2018/Office NEO Compound File Document Heap-based memory corruption


📈 25.38 Punkte











matomo