title: Is there a way to not have part of canvas reload every time state is changed in React?
body: <p>I just added the <code>react-color</code> module to this canvas page. When the user picks a color, the <code>strokeStyle</code> correctly changes to that color, but it also resets the entire canvas, making it a blank slate. Is there any way to change this so just the color itself changes but the canvas doesn't reset? I tried adding <code>shouldComponentUpdate</code> but that only made it so the color didn't change at all.</p>
  
  <pre><code>import React from 'react';
  import { Layer, Stage, Image } from 'react-konva';
  import { connect } from 'react-redux';
  import { bindActionCreators } from 'redux';
  import { GithubPicker } from 'react-color';
  
  class Canvas extends React.Component {
    constructor(props) {
      super(props);
      this.canvasEvent = this.canvasEvent.bind(this);
      this.props.socket.on('canvas_update', data =&gt; {
        const idToUpdate = data.canvasId == 1 ? 'drawing2' : 'drawing1';
        const node = document.createElement('p');
        const textNode = document.createTextNode('test');
        node.appendChild(textNode);
        document.getElementById(idToUpdate).appendChild(node);
        console.log(data.canvasJSON);
        this.updateKonva(idToUpdate, data.canvasJSON);
  
        //this.renderDisabledKonva(undefined, data.canvasJSON, data.canvasId);
      });
      this.state = {
        background: '#fff',
      };
    }
  
    canvasEvent(canvasJSON) {
      this.props.socket.emit('canvas_event', { roomId: this.props.roomId, canvasJSON: canvasJSON, canvasId: this.props.canvasId }, () =&gt; {});
    }
  
    handleChangeComplete = (color) =&gt; {
      this.setState({ background: color.hex });
    };
  
    renderTools() {
      return (
        &lt;div className="tool"&gt;
          Tool:
          &lt;select id="tool"&gt;
            &lt;option value="brush"&gt;Brush&lt;/option&gt;
            &lt;option value="eraser"&gt;Eraser&lt;/option&gt;
          &lt;/select&gt;
        &lt;/div&gt;
      );
    }
  
    renderKonva(container) {
      const that = this;
      const width = 400; // window.innerWidth;
      const height = 400; // window.innerHeight - 25;
      // first we need Konva core things: stage and layer
      const stage = new Konva.Stage({
        container: `drawing${this.props.canvasId}`,
        width: width,
        height: height
      });
      const layer = new Konva.Layer({});
      stage.add(layer);
      // then we are going to draw into special canvas element
      const canvas = document.createElement('canvas');
      canvas.width = stage.width() / 1.5;
      canvas.height = stage.height() / 1.5;
      // created canvas we can add to layer as 'Konva.Image' element
      let image = new Konva.Image({
        image: canvas,
        x: stage.width() / 6,
        y: stage.height() / 6,
        stroke: '#05AFF2',
        shadowBlur: 5,
      });
      layer.add(image);
      stage.draw();
      // Now we need to get access to context element
      const context = canvas.getContext('2d');
      context.strokeStyle = this.state.background;
      context.lineJoin = 'round';
      context.lineWidth = 5;
      let isPaint = false;
      let lastPointerPosition;
      let mode = 'brush';
      // now we need to bind some events
      // we need to start drawing on mousedown
      // and stop drawing on mouseup
      stage.on('contentMousedown.proto', () =&gt; {
        isPaint = true;
        lastPointerPosition = stage.getPointerPosition();
      });
      stage.on('contentMouseup.proto', () =&gt; {
        isPaint = false;
      });
      // and core function - drawing
      stage.on('contentMousemove.proto', () =&gt; {
        if (!isPaint) {
          return;
        }
        if (mode === 'brush') {
          context.lineWidth = 5;
          context.globalCompositeOperation = 'source-over';
        }
        if (mode === 'eraser') {
          context.lineWidth = 15;
          context.globalCompositeOperation = 'destination-out';
        }
        context.beginPath();
        let localPos = {
          x: lastPointerPosition.x - image.x(),
          y: lastPointerPosition.y - image.y(),
        };
        context.moveTo(localPos.x, localPos.y);
        const pos = stage.getPointerPosition();
        localPos = {
          x: pos.x - image.x(),
          y: pos.y - image.y(),
        };
        context.lineTo(localPos.x, localPos.y);
        context.closePath();
        context.stroke();
        lastPointerPosition = pos;
        layer.draw();
  
        const dataURL = stage.toDataURL();
        // window.open(dataURL);
        that.canvasEvent(dataURL);
        // that.canvasEvent(stage.toJSON());
        // console.log(layer);
      });
      const select = document.getElementById('tool');
      select.addEventListener('change', () =&gt; {
        mode = select.value;
      });
    }
  
    render() {
      return (
        &lt;div className="container"&gt;
          {this.renderTools()}
          &lt;GithubPicker onChangeComplete={this.handleChangeComplete} color={this.state.background} /&gt;
          &lt;div id={'drawing' + this.props.canvasId} ref={ref =&gt; this.renderKonva(ref)} /&gt;
        &lt;/div&gt;
      );
    }
  }
  
  const mapStateToProps = state =&gt; ({
    isAuthenticated: state.authReducer.isAuthenticated,
    user: state.authReducer,
    roomId: state.roomReducer.currentUserRoom,
  });
  
  const mapDispatchToProps = dispatch =&gt; bindActionCreators({}, dispatch);
  
  export default connect(mapStateToProps, mapDispatchToProps)(Canvas);
  </code></pre>