{"componentChunkName":"component---src-templates-blog-js","path":"/blog/2016/01/08/A-implies-B-does-not-imply-B-implies-A.html","result":{"data":{"markdownRemark":{"html":"<p>The documentation for <code class=\"gatsby-code-text\">componentWillReceiveProps</code> states that <code class=\"gatsby-code-text\">componentWillReceiveProps</code> will be invoked when the props change as the result of a rerender. Some people assume this means “if <code class=\"gatsby-code-text\">componentWillReceiveProps</code> is called, then the props must have changed”, but that conclusion is logically incorrect.</p>\n<p>The guiding principle is one of my favorites from formal logic/mathematics:</p>\n<blockquote>\n<p>A implies B does not imply B implies A</p>\n</blockquote>\n<p>Example: “If I eat moldy food, then I will get sick” does not imply “if I am sick, then I must have eaten moldy food”. There are many other reasons I could be feeling sick. For instance, maybe the flu is circulating around the office. Similarly, there are many reasons that <code class=\"gatsby-code-text\">componentWillReceiveProps</code> might get called, even if the props didn’t change.</p>\n<p>If you don’t believe me, call <code class=\"gatsby-code-text\">ReactDOM.render()</code> three times with the exact same props, and try to predict the number of times <code class=\"gatsby-code-text\">componentWillReceiveProps</code> will get called:</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre class=\"gatsby-code-jsx\"><code class=\"gatsby-code-jsx\"><span class=\"token keyword\">class</span> <span class=\"token class-name\">Component</span> <span class=\"token keyword\">extends</span> <span class=\"token class-name\">React<span class=\"token punctuation\">.</span>Component</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token function\">componentWillReceiveProps</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">nextProps</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token string\">'componentWillReceiveProps'</span><span class=\"token punctuation\">,</span> nextProps<span class=\"token punctuation\">.</span>data<span class=\"token punctuation\">.</span>bar<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n  <span class=\"token function\">render</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">return</span> <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>div</span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">Bar </span><span class=\"token punctuation\">{</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>props<span class=\"token punctuation\">.</span>data<span class=\"token punctuation\">.</span>bar<span class=\"token punctuation\">}</span><span class=\"token plain-text\">!</span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>div</span><span class=\"token punctuation\">></span></span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token keyword\">var</span> container <span class=\"token operator\">=</span> document<span class=\"token punctuation\">.</span><span class=\"token function\">getElementById</span><span class=\"token punctuation\">(</span><span class=\"token string\">'container'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">var</span> mydata <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span>bar<span class=\"token operator\">:</span> <span class=\"token string\">'drinks'</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\nReactDOM<span class=\"token punctuation\">.</span><span class=\"token function\">render</span><span class=\"token punctuation\">(</span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">Component</span></span> <span class=\"token attr-name\">data</span><span class=\"token script language-javascript\"><span class=\"token script-punctuation punctuation\">=</span><span class=\"token punctuation\">{</span>mydata<span class=\"token punctuation\">}</span></span> <span class=\"token punctuation\">/></span></span><span class=\"token punctuation\">,</span> container<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\nReactDOM<span class=\"token punctuation\">.</span><span class=\"token function\">render</span><span class=\"token punctuation\">(</span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">Component</span></span> <span class=\"token attr-name\">data</span><span class=\"token script language-javascript\"><span class=\"token script-punctuation punctuation\">=</span><span class=\"token punctuation\">{</span>mydata<span class=\"token punctuation\">}</span></span> <span class=\"token punctuation\">/></span></span><span class=\"token punctuation\">,</span> container<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\nReactDOM<span class=\"token punctuation\">.</span><span class=\"token function\">render</span><span class=\"token punctuation\">(</span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">Component</span></span> <span class=\"token attr-name\">data</span><span class=\"token script language-javascript\"><span class=\"token script-punctuation punctuation\">=</span><span class=\"token punctuation\">{</span>mydata<span class=\"token punctuation\">}</span></span> <span class=\"token punctuation\">/></span></span><span class=\"token punctuation\">,</span> container<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>In this case, the answer is “2”. React calls <code class=\"gatsby-code-text\">componentWillReceiveProps</code> twice (once for each of the two updates). Both times, the value of “drinks” is printed (ie. the props didn’t change).</p>\n<p>To understand why, we need to think about what <em>could</em> have happened. The data <em>could</em> have changed between the initial render and the two subsequent updates, if the code had performed a mutation like this:</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre class=\"gatsby-code-jsx\"><code class=\"gatsby-code-jsx\"><span class=\"token keyword\">var</span> mydata <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span>bar<span class=\"token operator\">:</span> <span class=\"token string\">'drinks'</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\nReactDOM<span class=\"token punctuation\">.</span><span class=\"token function\">render</span><span class=\"token punctuation\">(</span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">Component</span></span> <span class=\"token attr-name\">data</span><span class=\"token script language-javascript\"><span class=\"token script-punctuation punctuation\">=</span><span class=\"token punctuation\">{</span>mydata<span class=\"token punctuation\">}</span></span> <span class=\"token punctuation\">/></span></span><span class=\"token punctuation\">,</span> container<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\nmydata<span class=\"token punctuation\">.</span>bar <span class=\"token operator\">=</span> <span class=\"token string\">'food'</span>\nReactDOM<span class=\"token punctuation\">.</span><span class=\"token function\">render</span><span class=\"token punctuation\">(</span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">Component</span></span> <span class=\"token attr-name\">data</span><span class=\"token script language-javascript\"><span class=\"token script-punctuation punctuation\">=</span><span class=\"token punctuation\">{</span>mydata<span class=\"token punctuation\">}</span></span> <span class=\"token punctuation\">/></span></span><span class=\"token punctuation\">,</span> container<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\nmydata<span class=\"token punctuation\">.</span>bar <span class=\"token operator\">=</span> <span class=\"token string\">'noise'</span>\nReactDOM<span class=\"token punctuation\">.</span><span class=\"token function\">render</span><span class=\"token punctuation\">(</span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">Component</span></span> <span class=\"token attr-name\">data</span><span class=\"token script language-javascript\"><span class=\"token script-punctuation punctuation\">=</span><span class=\"token punctuation\">{</span>mydata<span class=\"token punctuation\">}</span></span> <span class=\"token punctuation\">/></span></span><span class=\"token punctuation\">,</span> container<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>React has no way of knowing that the data didn’t change. Therefore, React needs to call <code class=\"gatsby-code-text\">componentWillReceiveProps</code>, because the component needs to be notified of the new props (even if the new props happen to be the same as the old props).</p>\n<p>You might think that React could just use smarter checks for equality, but there are some issues with this idea:</p>\n<ul>\n<li>The old <code class=\"gatsby-code-text\">mydata</code> and the new <code class=\"gatsby-code-text\">mydata</code> are actually the same physical object (only the object’s internal value changed). Since the references are triple-equals-equal, doing an equality check doesn’t tell us if the value has changed. The only possible solution would be to have created a deep copy of the data, and then later do a deep comparison - but this can be prohibitively expensive for large data structures (especially ones with cycles).</li>\n<li>The <code class=\"gatsby-code-text\">mydata</code> object might contain references to functions which have captured variables within closures. There is no way for React to peek into these closures, and thus no way for React to copy them and/or verify equality.</li>\n<li>The <code class=\"gatsby-code-text\">mydata</code> object might contain references to objects which are re-instantiated during the parent’s render (ie. not triple-equals-equal) but are conceptually equal (ie. same keys and same values). A deep-compare (expensive) could detect this, except that functions present a problem again because there is no reliable way to compare two functions to see if they are semantically equivalent.</li>\n</ul>\n<p>Given the language constraints, it is sometimes impossible for us to achieve meaningful equality semantics. In such cases, React will call <code class=\"gatsby-code-text\">componentWillReceiveProps</code> (even though the props might not have changed) so the component has an opportunity to examine the new props and act accordingly.</p>\n<p>As a result, your implementation of <code class=\"gatsby-code-text\">componentWillReceiveProps</code> MUST NOT assume that your props have changed. If you want an operation (such as a network request) to occur only when props have changed, your <code class=\"gatsby-code-text\">componentWillReceiveProps</code> code needs to check to see if the props actually changed.</p>","excerpt":"The documentation for  states that  will be invoked when the props change as the result of a rerender. Some people assume this means “if  is called, then the props must have changed”, but that conclusion is logically incorrect. The guiding principle is one of my favorites from formal logic/mathematics: A implies B does not imply B implies A Example: “If I eat moldy food, then I will get sick” does not imply “if I am sick, then I must have eaten moldy food”. There are many other reasons I could…","frontmatter":{"title":"(A => B) !=> (B => A)","next":null,"prev":null,"author":[{"frontmatter":{"name":"Jim Sproch","url":"http://www.jimsproch.com"}}]},"fields":{"date":"January 08, 2016","path":"content/blog/2016-01-08-A-implies-B-does-not-imply-B-implies-A.md","slug":"/blog/2016/01/08/A-implies-B-does-not-imply-B-implies-A.html"}},"allMarkdownRemark":{"edges":[{"node":{"frontmatter":{"title":"Introducing the New JSX Transform"},"fields":{"slug":"/blog/2020/09/22/introducing-the-new-jsx-transform.html"}}},{"node":{"frontmatter":{"title":"React v17.0 Release Candidate: No New Features"},"fields":{"slug":"/blog/2020/08/10/react-v17-rc.html"}}},{"node":{"frontmatter":{"title":"React v16.13.0"},"fields":{"slug":"/blog/2020/02/26/react-v16.13.0.html"}}},{"node":{"frontmatter":{"title":"Building Great User Experiences with Concurrent Mode and Suspense"},"fields":{"slug":"/blog/2019/11/06/building-great-user-experiences-with-concurrent-mode-and-suspense.html"}}},{"node":{"frontmatter":{"title":"Preparing for the Future with React Prereleases"},"fields":{"slug":"/blog/2019/10/22/react-release-channels.html"}}},{"node":{"frontmatter":{"title":"Introducing the New React DevTools"},"fields":{"slug":"/blog/2019/08/15/new-react-devtools.html"}}},{"node":{"frontmatter":{"title":"React v16.9.0 and the Roadmap Update"},"fields":{"slug":"/blog/2019/08/08/react-v16.9.0.html"}}},{"node":{"frontmatter":{"title":"Is React Translated Yet? ¡Sí! Sim! はい！"},"fields":{"slug":"/blog/2019/02/23/is-react-translated-yet.html"}}},{"node":{"frontmatter":{"title":"React v16.8: The One With Hooks"},"fields":{"slug":"/blog/2019/02/06/react-v16.8.0.html"}}},{"node":{"frontmatter":{"title":"React v16.7: No, This Is Not the One With Hooks"},"fields":{"slug":"/blog/2018/12/19/react-v-16-7.html"}}}]}},"pageContext":{"slug":"/blog/2016/01/08/A-implies-B-does-not-imply-B-implies-A.html"}},"staticQueryHashes":[]}