Home > Net >  How to use useState with dynamically added elements?
How to use useState with dynamically added elements?

Time:11-13

I have a canvas and when i click on it, it draws a line.

Line is a function:

const line = (x1, y1, x2, y2) => {
  return (
    <line id="lineD" x1={x1} y1={y1} x2={x2} y2={y2} style={{ stroke: "black", strokeWidth: 3, strokeLinecap: "round" }}></line>
    )
}

It works fine, except when I scale the canvas. When I do so, I change a scale state.

So I want line attributes to be like this: x1={x1 * scale}, but it only sets it once.

This is how I add lines, (content is another state):

content.push(line(100, 100, 200, 200))

(these are just random numbers)
And svg is: <svg>{content}</svg>

CodePudding user response:

React is "reacting" only to state or props update. Since your line function returns JSX, you should turn it into a real React component and pass your data as props to make the rendering dynamic. Something like that:

const Line = (props) => {
  const {x1, y1, x2, y2, scale} = props;
  return (
    <line id="lineD" x1={x1 * scale} y1={y1 * scale} x2={x2 * scale} y2={y2 * scale} style={{ stroke: "black", strokeWidth: 3, strokeLinecap: "round" }}></line>
  );
}

Note the uppercase L in Line: this is mandatory for React to see it as a component. Then you may use it to produce your array:

content.push(<Line x1={100} y2={100} x2={200} y2={200} scale={scale} />) 

But a state should not be muted. You should use the set function you get from useState:

const [content, setContent] = useState([]);

...

// do the following in an event handler, or in a useEffect
setContent([...content, <Line x1={100} y2={100} x2={200} y2={200} scale={scale} />]);

This will update the state and trigger a new rendering

  • Related