简体   繁体   中英

Is using a Canvas element in a React component inherently inefficient?

Question context: I'm creating a pixel art app using React and Redux and the editor portion is an HTML canvas. The grid containing the pixels is drawn on the canvas and meant to be updated whenever the piece of state containing the color of each pixel is updated. State also manages what tool is currently being used in the editor as well as the size of the canvas.

Question

Normal updates to the canvas are just pushing pixels on a bitmap. However, in React, whenever state changes affect a component, it re-renders by default. So if you updated the canvas in the normal React way using componentDidUpdate() , you aren't just clearing and then redrawing the bitmap—you're re-rendering the entire canvas DOM element every time. That seems incredibly wasteful to me.

Is the re-rendering of the canvas element a potential performance bottleneck?

If so, what are some good solutions you've used or seen out in the wild?

Some ideas of mine: I know you can set shouldComponentUpdate() to return false so it won't re-render but then you won't be able to use componentDidUpdate() to fire off an updateCanvas() function when the state changes. I figure the solution might require some wrestling with React-Redux and Redux source to get the canvas to subscribe to the store directly without using React. This is not something I've tried before but I can see how it might work.

Update: So according to someone else I talked to on another forum, as long as state update's don't change the result of the JSX, react is smart enough not to re-render the DOM element. Grabbing the ref to canvas and updating it that way shouldn't re-render the DOM element. Is this something anyone can confirm/provide a deeper explanation for?

I think there is no solution. You are doing ok. React hás a difing algorithm that allows react to be smart as your friend told you. You can read more here on https://reactjs.org/docs/reconciliation.html .

Since you are redrawimg canvas, te only solution I can thing of is delaying te next render in case of drags for exemple.

The solution that worked for me while working with pixi.js and three.js is avoid the react render and reconciliation by returning false in shouldComponentUpdate() function and updating the canvas with plain js and events (cleaning listeners on componentWillUnmount). There is no real benefit to take andvantage of react when working with canvas. I suggest you a interesting reading on topic: https://medium.com/@tibotiber/react-d3-js-balancing-performance-developer-experience-4da35f912484

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM