Search code examples
cssreactjsuse-effectuse-state

How can I reuse a component with different props in React?


I have a parent component where I need to reuse a child component called Chart several times but with different props, but what happens is that the first component is the only one that is modified and also by the props of the last Chart component.

I understand that the center number is modified by the return of the component, but how can I do the logic inside the useEffect? I am new to React if someone could help me, thanks.

The code

const Dashboard = () => {
  return (
    <>
      <div className="chartContainerMain">
        <div className="chartsContainer">
          <div className="chartContainer">
            <p className="nameChart">chart 1</p>
            <Chart color="red" number={45} /> ///// This is the component i need
            to reuse
          </div>

          <div className="chartContainer">
            <p className="nameChart">chart 2</p>
            <Chart color="blue" number={90} /> ///// This is the component i
            need to reuse
          </div>
        </div>
      </div>
    </>
  );
};

export default Dashboard;

//-------- COMPONENT CHART CODE ---------------[![enter image description here][1]][1]

import { useEffect } from "react";
import "./chart.css";

const Chart = ({ color, number }) => {
  useEffect(() => {
    let circle = document.querySelector(".circle");
    circle.style.strokeDasharray = `${number} 100`;
    circle.style.stroke = `${color}`;
  }, [color, number]);

  return (
    <>
      <div className="donut-chart">
        <svg viewBox="0 0 32 32">
          <circle className="circle" r="16" cx="16" cy="16" />
        </svg>
        <div className="donut-center">
          <p className="centerNumber">{number}%</p>
        </div>
      </div>
    </>
  );
};

export default Chart;

You can see this image https://i.sstatic.net/762F6.png


Solution

  • The problem you're running into likely has to do with the fact that you're trying to use the <Chart /> component to modify a DOM node (document.querySelector(".circle")) directly, especially since document.querySelector(".circle") will return the first element it finds. Instead your <Chart /> component itself should render that node and apply whatever styles you need to it based on the props. You probably don't need the useEffect hook at all...

    const Chart = ({ color, number }) => {
      return (
        <>
          <div className="donut-chart">
            <svg viewBox="0 0 32 32">
              <circle className="circle"
                      r="16"
                      cx="16"
                      cy="16"
                      style={{strokeDasharray: `${number} 100`, stroke: color}}/>
            </svg>
            <div className="donut-center">
              <p className="centerNumber">{number}%</p>
            </div>
          </div>
        </>
      );
    };
    
    export default Chart;
    
    

    I'm not too sure what the exact problem you're running into is, but based on your question and code sample, hopefully this helps, or at least points you in the right direction.