<h2 dir="auto">Since I can not re-open other's issue, I am opening this issue to address a potential type check issue that is causing a lot unexpected behavior on other issues.</h2>
<p dir="auto">After viewing the source code and confused by <code class="notranslate">handleStateChange</code> rename to <code class="notranslate">onParentShouldUpdate</code>; <code class="notranslate">onCheck</code> rename to <code class="notranslate">handleCheck</code> then rename to <code class="notranslate">onSwitch</code> and massive unifying code on the EnhancedSwitch,<br>
I think my recent project found the root of this issues. ( I really think the source code need to refactor a bit to read it easier.<br>
<code class="notranslate">//sorry for the complaining but it is really confusing and hard to keep track of the function name</code></p>
<h2 dir="auto">Root of the problem</h2>
<h3 dir="auto">Applying on <code class="notranslate">onCheck()</code> usually cause an <code class="notranslate">setState()</code> on the <code class="notranslate">owner Element</code></h3>
<p dir="auto">This will also trigger a <code class="notranslate">render()</code> lifecycle event on the <code class="notranslate">owner Element</code><br>
In React when Owner <code class="notranslate">render()</code> it triggers the <code class="notranslate">componentWillReceiveProps()</code> on its child, in our case the <code class="notranslate">&lt;Checkbox /&gt;</code><br>
In the <code class="notranslate">componentWillReceiveProps</code></p>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="componentWillReceiveProps(nextProps) {
    this.setState({
      switched: this.props.checked !== nextProps.checked ?
        nextProps.checked :
        this.state.switched,
    });
  }"><pre class="notranslate"><span class="pl-en">componentWillReceiveProps</span><span class="pl-kos">(</span><span class="pl-s1">nextProps</span><span class="pl-kos">)</span><span class="pl-kos"></span> <span class="pl-kos">{</span>
    <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-en">setState</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
      <span class="pl-c1">switched</span>: <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">props</span><span class="pl-kos">.</span><span class="pl-c1">checked</span> <span class="pl-c1">!==</span> <span class="pl-s1">nextProps</span><span class="pl-kos">.</span><span class="pl-c1">checked</span> ?
        <span class="pl-s1">nextProps</span><span class="pl-kos">.</span><span class="pl-c1">checked</span> :
        <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">state</span><span class="pl-kos">.</span><span class="pl-c1">switched</span><span class="pl-kos">,</span>
    <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
  <span class="pl-kos">}</span></pre></div>
<h3 dir="auto">Normally if <code class="notranslate">onCheck()</code> and <code class="notranslate">checked</code> are provided the update looks like this</h3>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="input.onChange(event) =&gt; EnhancedSwitch.handleChange(event) =&gt; 
EnhancedSwitch.onSwitch(event, isInputChecked) === Checkbox.handleCheck(e, v) === Checkbox.onCheck(e, v) =&gt; 
Owner.onCheck(v) =&gt; Owner.setState() =&gt; Owner.render() =&gt; 
Checkbox.componentWillReceiveProps() =&gt; Checkbox.setState({switched:nextProps.checked}); =&gt;
Checkbox.render() =&gt; EnhancedSwitch.componentWillReceiveProps() =&gt; 
EnhancedSwitch.setState(switched: nextProps.checked) =&gt; input.value = isInputChecked"><pre class="notranslate"><span class="pl-s1">input</span><span class="pl-kos">.</span><span class="pl-en">onChange</span><span class="pl-kos">(</span><span class="pl-s1">event</span><span class="pl-kos">)</span> <span class="pl-c1">=</span><span class="pl-c1">&gt;</span> <span class="pl-v">EnhancedSwitch</span><span class="pl-kos">.</span><span class="pl-en">handleChange</span><span class="pl-kos">(</span><span class="pl-s1">event</span><span class="pl-kos">)</span> <span class="pl-c1">=</span><span class="pl-c1">&gt;</span> 
<span class="pl-v">EnhancedSwitch</span><span class="pl-kos">.</span><span class="pl-en">onSwitch</span><span class="pl-kos">(</span><span class="pl-s1">event</span><span class="pl-kos">,</span> <span class="pl-s1">isInputChecked</span><span class="pl-kos">)</span> <span class="pl-c1">===</span> <span class="pl-v">Checkbox</span><span class="pl-kos">.</span><span class="pl-en">handleCheck</span><span class="pl-kos">(</span><span class="pl-s1">e</span><span class="pl-kos">,</span> <span class="pl-s1">v</span><span class="pl-kos">)</span> <span class="pl-c1">===</span> <span class="pl-v">Checkbox</span><span class="pl-kos">.</span><span class="pl-en">onCheck</span><span class="pl-kos">(</span><span class="pl-s1">e</span><span class="pl-kos">,</span> <span class="pl-s1">v</span><span class="pl-kos">)</span> <span class="pl-c1">=</span><span class="pl-c1">&gt;</span> 
<span class="pl-v">Owner</span><span class="pl-kos">.</span><span class="pl-en">onCheck</span><span class="pl-kos">(</span><span class="pl-s1">v</span><span class="pl-kos">)</span> <span class="pl-c1">=</span><span class="pl-c1">&gt;</span> <span class="pl-v">Owner</span><span class="pl-kos">.</span><span class="pl-en">setState</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-c1">=</span><span class="pl-c1">&gt;</span> <span class="pl-v">Owner</span><span class="pl-kos">.</span><span class="pl-en">render</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-c1">=</span><span class="pl-c1">&gt;</span> 
<span class="pl-v">Checkbox</span><span class="pl-kos">.</span><span class="pl-en">componentWillReceiveProps</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-c1">=</span><span class="pl-c1">&gt;</span> <span class="pl-v">Checkbox</span><span class="pl-kos">.</span><span class="pl-en">setState</span><span class="pl-kos">(</span><span class="pl-kos">{</span><span class="pl-c1">switched</span>:<span class="pl-s1">nextProps</span><span class="pl-kos">.</span><span class="pl-c1">checked</span><span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c1">=&gt;</span>
<span class="pl-v">Checkbox</span><span class="pl-kos">.</span><span class="pl-en">render</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-c1">=</span><span class="pl-c1">&gt;</span> <span class="pl-v">EnhancedSwitch</span><span class="pl-kos">.</span><span class="pl-en">componentWillReceiveProps</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-c1">=</span><span class="pl-c1">&gt;</span> 
<span class="pl-v">EnhancedSwitch</span><span class="pl-kos">.</span><span class="pl-en">setState</span><span class="pl-kos">(</span><span class="pl-s1">switched</span>: <span class="pl-s1">nextProps</span><span class="pl-kos">.</span><span class="pl-c1">checked</span><span class="pl-kos">)</span> <span class="pl-c1">=</span><span class="pl-c1">&gt;</span> <span class="pl-s1">input</span><span class="pl-kos">.</span><span class="pl-c1">value</span> <span class="pl-c1">=</span> <span class="pl-s1">isInputChecked</span></pre></div>
<h3 dir="auto">But  If <code class="notranslate">onCheck()</code> is provided but no <code class="notranslate">check</code> or <code class="notranslate">value</code> provided Checkbox lifecycle event becomes</h3>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="componentWillReceiveProps(nextProps) {
    this.setState({
      switched: this.props.checked !== nextProps.checked ? // undefined !== undefined =&gt; always false
        nextProps.checked :
        this.state.switched,
    });
  }
 =&gt; this.setState({switched: this.state.switched}); "><pre class="notranslate"><span class="pl-en">componentWillReceiveProps</span><span class="pl-kos">(</span><span class="pl-s1">nextProps</span><span class="pl-kos">)</span><span class="pl-kos"></span> <span class="pl-kos">{</span>
    <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-en">setState</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
      <span class="pl-c1">switched</span>: <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">props</span><span class="pl-kos">.</span><span class="pl-c1">checked</span> <span class="pl-c1">!==</span> <span class="pl-s1">nextProps</span><span class="pl-kos">.</span><span class="pl-c1">checked</span> ? <span class="pl-c">// undefined !== undefined =&gt; always false</span>
        <span class="pl-s1">nextProps</span><span class="pl-kos">.</span><span class="pl-c1">checked</span> :
        <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">state</span><span class="pl-kos">.</span><span class="pl-c1">switched</span><span class="pl-kos">,</span>
    <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
  <span class="pl-kos">}</span>
 <span class="pl-c1">=&gt;</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-en">setState</span><span class="pl-kos">(</span><span class="pl-kos">{</span><span class="pl-c1">switched</span>: <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">state</span><span class="pl-kos">.</span><span class="pl-c1">switched</span><span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span> </pre></div>
<p dir="auto">this is a duplicate setState that we did not anticipate. Since we do not provide a <code class="notranslate">check</code> props to the Checkbox, the Checkbox should be the state container for EnhancedSwitch and handle its own state, but <code class="notranslate">Owner.render()</code> is called in the same call stack <code class="notranslate">this.setState()</code> inside <code class="notranslate">Checkbox.handleStateChange</code>.</p>
<blockquote>
<p dir="auto">So the actual render we get is the<br>
<code class="notranslate">this.setState()</code> inside <code class="notranslate">Checkbox.handleStateChange</code><br>
and<br>
<code class="notranslate">this.setState()</code> inside <code class="notranslate">Checkbox.componentWillReceiveProps</code><br>
batched together.</p>
</blockquote>
<p dir="auto">A fix should not be a <code class="notranslate">setTimeout( () =&gt; this.setState()</code> on the <code class="notranslate">Owner</code>. <code class="notranslate">Checkbox</code> nor <code class="notranslate">EnhancedSwitch</code></p>
<h3 dir="auto">It should be a simple type check inside the componentWillReceiveProps</h3>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="componentWillReceiveProps(nextProps) {
  if(nextProps.checked !== undefined) {
    this.setState({
      switched: this.props.checked !== nextProps.checked ? nextProps.checked : this.state.switched
    });
  }"><pre class="notranslate"><span class="pl-en">componentWillReceiveProps</span><span class="pl-kos">(</span><span class="pl-s1">nextProps</span><span class="pl-kos">)</span><span class="pl-kos"></span> <span class="pl-kos">{</span>
  <span class="pl-k">if</span><span class="pl-kos">(</span><span class="pl-s1">nextProps</span><span class="pl-kos">.</span><span class="pl-c1">checked</span> <span class="pl-c1">!==</span> <span class="pl-c1">undefined</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-en">setState</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
      <span class="pl-c1">switched</span>: <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">props</span><span class="pl-kos">.</span><span class="pl-c1">checked</span> <span class="pl-c1">!==</span> <span class="pl-s1">nextProps</span><span class="pl-kos">.</span><span class="pl-c1">checked</span> ? <span class="pl-s1">nextProps</span><span class="pl-kos">.</span><span class="pl-c1">checked</span> : <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">state</span><span class="pl-kos">.</span><span class="pl-c1">switched</span>
    <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
  <span class="pl-kos">}</span><span class="pl-kos"></span></pre></div>
<p dir="auto">setTimeout simply change the order of the render and setState;</p>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="Checkbox.handleStateChange(event, true);

//normal setState
Checkbox setState({switch:true}) Finished
Owner setState() Finished
Owner rendering
Checkbox componentWillReceiveProps
    Checkbox state: false =&gt; Checkbox setState({switch:false});
    //React auto batched two setState() then render
Checkbox rendering
EnhancedSwitch rendering

//setTimeout setState
Checkbox setState() Finished
Owner setTimeout setState() Finished  //push setState() to event loop out of the current call stack 
Checkbox rendering()              //on rendering the Checkbox state updated
EnhancedSwitch rendering()   //this prioritized Checkbox setState() =&gt; render() to run next
Owner rendering()                   //current stack is empty, next call in event loop is Owner
Checkbox componentWillReceiveProps
    Checkbox state: true =&gt; Checkbox setState({switch:true});
Checkbox rendering()             
EnhancedSwitch render()"><pre class="notranslate"><span class="pl-v">Checkbox</span><span class="pl-kos">.</span><span class="pl-en">handleStateChange</span><span class="pl-kos">(</span><span class="pl-s1">event</span><span class="pl-kos">,</span> <span class="pl-c1">true</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-c">//normal setState</span>
<span class="pl-v">Checkbox</span> <span class="pl-s1">setState</span><span class="pl-kos">(</span><span class="pl-kos">{</span><span class="pl-c1">switch</span>:<span class="pl-c1">true</span><span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos"></span> <span class="pl-v">Finished</span>
<span class="pl-v">Owner</span> <span class="pl-s1">setState</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos"></span> <span class="pl-v">Finished</span>
<span class="pl-v">Owner</span><span class="pl-kos"></span> <span class="pl-s1">rendering</span>
<span class="pl-v">Checkbox</span><span class="pl-kos"></span> <span class="pl-s1">componentWillReceiveProps</span>
    <span class="pl-v">Checkbox</span> <span class="pl-s1">state</span>: <span class="pl-c1">false</span> <span class="pl-c1">=&gt;</span> <span class="pl-v">Checkbox</span> <span class="pl-en">setState</span><span class="pl-kos">(</span><span class="pl-kos">{</span><span class="pl-c1">switch</span>:<span class="pl-c1">false</span><span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-c">//React auto batched two setState() then render</span>
<span class="pl-v">Checkbox</span><span class="pl-kos"></span> <span class="pl-s1">rendering</span>
<span class="pl-v">EnhancedSwitch</span><span class="pl-kos"></span> <span class="pl-s1">rendering</span>

<span class="pl-c">//setTimeout setState</span>
<span class="pl-v">Checkbox</span> <span class="pl-s1">setState</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos"></span> <span class="pl-v">Finished</span>
<span class="pl-v">Owner</span> <span class="pl-s1">setTimeout</span> <span class="pl-en">setState</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos"></span> <span class="pl-v">Finished</span>  <span class="pl-c">//push setState() to event loop out of the current call stack </span>
<span class="pl-v">Checkbox</span> <span class="pl-s1">rendering</span><span class="pl-kos">(</span><span class="pl-kos">)</span>              <span class="pl-c">//on rendering the Checkbox state updated</span>
<span class="pl-v">EnhancedSwitch</span> <span class="pl-s1">rendering</span><span class="pl-kos">(</span><span class="pl-kos">)</span>   <span class="pl-c">//this prioritized Checkbox setState() =&gt; render() to run next</span>
<span class="pl-v">Owner</span> <span class="pl-s1">rendering</span><span class="pl-kos">(</span><span class="pl-kos">)</span>                   <span class="pl-c">//current stack is empty, next call in event loop is Owner</span>
<span class="pl-v">Checkbox</span><span class="pl-kos"></span> <span class="pl-s1">componentWillReceiveProps</span>
    <span class="pl-v">Checkbox</span> <span class="pl-s1">state</span>: <span class="pl-c1">true</span> <span class="pl-c1">=&gt;</span> <span class="pl-v">Checkbox</span> <span class="pl-en">setState</span><span class="pl-kos">(</span><span class="pl-kos">{</span><span class="pl-c1">switch</span>:<span class="pl-c1">true</span><span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-v">Checkbox</span> <span class="pl-s1">rendering</span><span class="pl-kos">(</span><span class="pl-kos">)</span>             
<span class="pl-v">EnhancedSwitch</span> <span class="pl-s1">render</span><span class="pl-kos">(</span><span class="pl-kos">)</span></pre></div>
<h4 dir="auto">If you want to learn more about the eventloop and setTimeout hack</h4>
<p dir="auto"><a href="https://www.youtube.com/watch?v=8aGhZQkoFbQ" rel="nofollow">Philip Roberts: What the heck is the event loop anyway? | JSConf EU 2014</a><br>
This is a really good video explaining what is happening.</p>
<h2 dir="auto">one note on controlled component</h2>
<p dir="auto">Only if you set the value of the input, it should be considered as a controlled component. For example, if I ever want to use google analytic to true my input actual usage I should only need to track it with <code class="notranslate">onCheck</code> rather than turn it into a controlled component.</p>
<h3 dir="auto">And allowing <code class="notranslate">onCheck</code> without making it a controlled component makes it skips tons of parent update.</h3>
<p dir="auto">In my case I render 30 check box as a feature list and I don't want my Owner component to render every time a checkbox change but only match the state to the selected. This allows me to skip Array.map many times and I notices this reduce the visual response time at least by 300ms.<br>
This library needs a lot performance and lifecycle hook refactoring. And this should be a good start.</p>
<h2 dir="auto">I am pretty new to how to open a PR or anything, but I will try it when I have time.</h2>
<p dir="auto">If you read this comment and understand the reason I think it should be a bugfix without changing anything else.<br>
Or we could discuss the state of <code class="notranslate">switch</code> and how to remove the <code class="notranslate">setState</code> in <code class="notranslate">WillReceiveProps</code>, this is a typical <a href="https://facebook.github.io/react/blog/2016/01/08/A-implies-B-does-not-imply-B-implies-A.html" rel="nofollow">A implies B does not imply B implies A</a> design issue.<br>
We should enforce a single source of truth, either as a state at top level component then the child will only use props as the source or as the actual value in the DOM input which need to connect with the correct lifecycle event to map to a state.</p>
<p dir="auto">Related and could correctly closed issue:<br>
<a href="https://github.com/puranjayjain/youtube-dl-gui/issues/24" data-hovercard-type="issue" data-hovercard-url="/puranjayjain/youtube-dl-gui/issues/24/hovercard">Checkboxes and toggles issue</a><br>
<a href="https://github.com/mbrookes/formsy-material-ui/issues/55" data-hovercard-type="issue" data-hovercard-url="/formsy/formsy-material-ui/issues/55/hovercard">Checkbox not updating</a><br>
<a href="https://github.com/callemall/material-ui/issues/2983" data-hovercard-type="issue" data-hovercard-url="/mui/material-ui/issues/2983/hovercard">[Checkbox] setting the state in onCheck doesn't display the checked box </a></p>
<p dir="auto">Related PR:<br>
<a href="https://github.com/callemall/material-ui/pull/4443" data-hovercard-type="pull_request" data-hovercard-url="/mui/material-ui/pull/4443/hovercard">[Toggle][Checkbox] setting the state in onCheck doesn't display the checked box</a><br>
<a href="https://github.com/callemall/material-ui/pull/4440" data-hovercard-type="pull_request" data-hovercard-url="/mui/material-ui/pull/4440/hovercard">fix [Toggle][Checkbox] setting the state in onCheck doesn't display the checked box</a></p>
<p dir="auto">Setting the state in the callback of <code class="notranslate">onCheck</code> event cancels the [V] mark on the selected box.<br>
Without setting the state, the checkbox works as expected.</p>
<p dir="auto">Working fine</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="&lt;Checkbox
                label=&quot;price&quot;
                onCheck={this._handleCBPrice.bind(this)} /&gt;
_handleCBPrice(event, checked){}"><pre class="notranslate"><code class="notranslate">&lt;Checkbox
                label="price"
                onCheck={this._handleCBPrice.bind(this)} /&gt;
_handleCBPrice(event, checked){}
</code></pre></div>
<p dir="auto">Doesn't mark the box with a [V]</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="&lt;Checkbox
                label=&quot;price&quot;
                onCheck={this._handleCBPrice.bind(this)} /&gt;

_handleCBPrice(event, checked){
     this.setState({someKey:someValue})
  }"><pre class="notranslate"><code class="notranslate">&lt;Checkbox
                label="price"
                onCheck={this._handleCBPrice.bind(this)} /&gt;

_handleCBPrice(event, checked){
     this.setState({someKey:someValue})
  }
</code></pre></div>