Raghu Datta
Raghu Datta

Reputation: 99

Re-render Canvas in React Js

I have a canvas which has grid data of 500 rows X 500 cols. I am trying to update few particular cells in React state, once react state is updated whole canvas is re-created and rendered. Is there any better way to update part of canvas? Below is the flow of component

  1. call API in componentDidMount() and save response in state.
  2. Using state create a canvas and render in UI
  3. Every 30 seconds call api and get data only updated data and update state.
  4. Currently, once state is updated, whole can is created and rendered
  5. Now can i update only latest updated state values in canvas?

Upvotes: 1

Views: 3673

Answers (1)

jaesle
jaesle

Reputation: 576

I don't believe that the number of items in the canvas is the issue. I'm guessing that the issue is that you need to update the items in the correct way. Here's an example using Hooks of how to update just parts of the canvas that are changing without changing everything. Obviously it would need to be adapted to your specific instance, but it should give you a direction on how you could do it.

function Canvas(props) {
  var item = 0;
  // pos is the item in the table that's going to be updated
  const [pos, setPos] = React.useState(0);
  //sample data
  const [A,setA] = React.useState([
    {data:"N", id:1},{data:"N",id :2},{data:"N",id :3},{data:"N",id :4}
   ]); 
  const totalitems = A.length;
  
  const canvasRef = React.useRef(null)
  
  function HandleClick() {
    let newArray = [...A];
    item=Math.floor(Math.random()*totalitems);
    // toggle between letters
    newArray[item].data == "N" ? newArray[item].data = "H" : newArray[item].data = "N" ; 
    setA(newArray); // set the entry in the array to the new letter
    setPos(item);
  };
    
  const tabledraw = ctx => {
    // The following line clears the whole canvas
    // ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height)

    ctx.fillStyle = '#000000';
    // Clear only part of the canvas that corresponds to the size
    // of the text that is being replaced
    ctx.clearRect(pos*50, 0,50, 100);
    ctx.font = "30px Arial";
    // translate the position of the start of the canvas to where the 
    // character that is changing is
    ctx.translate(pos*50,0);
    ctx.fillText(A[pos].data, 0, 80);
    // Translate the canvas back to its original position
    ctx.translate(-pos*50,0);
    }
  
React.useEffect(() => {
    const canvas = canvasRef.current
    const context = canvas.getContext('2d')
    tabledraw(context)
    }, [tabledraw])
  
  return(
   <>
   <canvas ref={canvasRef} {...props}/>
   <button onClick={HandleClick}>Change</button>
   </>
  )
}

Upvotes: 1

Related Questions