Draw dynamic circle in gatsby react issue

Viewed 64

I am using Strapi as a backend, and in my frontend I am using Gatsby.

I am using the values from the backend to draw a circle inside a card. The number of cards are generated from the backend value.

For now I am hard coding the three first cards in css with n:th child values with the following css code:

.svgAssesment circle {
  width: 100%;
  height: 100%;
  fill: none;
  stroke-width: 10;
  stroke: rgba(255, 255, 255, 0.05);
  transform: translate(5px, 5px);
  stroke-linecap: round;
}
.svgAssesment circle:nth-child(2) {
  stroke: #fff;
  stroke-dasharray: 440px;
}
.card:nth-child(1) .svgAssesment circle:nth-child(2) {
  stroke-dashoffset: calc(440px - (440px * 9) / 10);
}
.card:nth-child(2) .svgAssesment circle:nth-child(2) {
  stroke-dashoffset: calc(440px - (440px * 9) / 10);
}
.card:nth-child(3) .svgAssesment circle:nth-child(2) {
  stroke-dashoffset: calc(440px - (440px * 8) / 10);
}

Instead of hard coding these values, is there a way to draw them dynamically so that each circle's stroke-dashoffset is based upon the prop {item.rate} I have in my frontend. So in the example above the hard coded values are 9,9 and 8 should be replaced with the values of {item.rate} for each of the cards generated and not just the three I have in my nth:child code.

This is my frontend code:

import React from "react"
import Title from "./Title"
import { graphql, useStaticQuery } from "gatsby"

    const query = graphql`
      {
        allStrapiAssessment {
          nodes {
            title
            rating {
              id
              topic
              rate
            }
          }
        }
      }
    `
    
    const SelfAssesment = () => {
      const data = useStaticQuery(query)
      //console.log(data)
    
      const {
        allStrapiAssessment: { nodes: assesments },
      } = data
      //console.log(assesments)
      const [value] = React.useState(0)
      const { title, rating } = assesments[value]
      console.log(title, rating)
    
      return (
        <section className="section jobs">
          <Title title={title} />
    
          <section className="assesment">
            <div className="container">
              {rating.map(item => {
                return (
                  <div key={item.id} className="card">
                    <div className="box">
                      <div>
                        <div class="percent">
                          <svg className="svgAssesment">
                            <circle cx="70" cy="70" r="70"></circle>
                            <circle cx="70" cy="70" r="70"></circle>
                          </svg>
                          <div class="number">
                            <h2>
                              {item.rate}
                              <span>/10</span>
                            </h2>
                          </div>
                        </div>
                      </div>
                    </div>
                    <div id="buttonColor" className="text">
                      {item.topic}
                    </div>
                  </div>
                )
              })}
            </div>
          </section>
        </section>
      )
    }
    
    export default SelfAssesment
1 Answers

You will need to use styled-components in order to use React props in the styling.

Alternatively, you can just use inline styles for stroke-dashoffset CSS rule and delegate the rest of the styling into your CSS stylesheet. Something like:

import React from "react"
import Title from "./Title"
import { graphql, useStaticQuery } from "gatsby"

const query = graphql`
  {
    allStrapiAssessment {
      nodes {
        title
        rating {
          id
          topic
          rate
        }
      }
    }
  }
`

const SelfAssesment = () => {
  const data = useStaticQuery(query)
  //console.log(data)

  const {
    allStrapiAssessment: { nodes: assesments },
  } = data
  //console.log(assesments)
  const [value] = React.useState(0)
  const { title, rating } = assesments[value]
  console.log(title, rating)

  return (
    <section className="section jobs">
      <Title title={title} />

      <section className="assesment">
        <div className="container">
          {rating.map(item => {
            return (
              <div key={item.id} className="card">
                <div className="box">
                  <div>
                    <div class="percent">
                      <svg className="svgAssesment">
                        <circle cx="70" cy="70" r="70"/>
                        <circle cx="70" cy="70" r="70" style={{ 
                          strokeDashoffset: `calc(440px - (440px * ${item.rate}) / 10)`
                        }}/>
                      </svg>
                      <div class="number">
                        <h2>
                          {item.rate}
                          <span>/10</span>
                        </h2>
                      </div>
                    </div>
                  </div>
                </div>
                <div id="buttonColor" className="text">
                  {item.topic}
                </div>
              </div>
            )
          })}
        </div>
      </section>
    </section>
  )
}

export default SelfAssesment

Note the:

 <circle cx="70" cy="70" r="70" style={{ 
    strokeDashoffset: `calc(440px - (440px * ${item.rate}) / 10)`
  }}/>

In the snippet above you are just calculating the stroke-dashoffset rule with inline styles applying the dynamic item.rate value in the second circle.

Related