<p dir="auto">The <a href="https://facebook.github.io/react/blog/2015/01/27/react-v0.13.0-beta-1.html" rel="nofollow">ES6 support announcement</a> says:</p>
<blockquote>
<p dir="auto">the idiomatic way to specify class state is to just use a simple instance property. Likewise getDefaultProps and propTypes are really just properties on the constructor.</p>
</blockquote>
<p dir="auto">This makes a lot of sense to me, but I noticed some small inconsistencies that may be worth rethinking.</p>
<p dir="auto">When using the original <code class="notranslate">.createClass</code> syntax, the value returned by <code class="notranslate">getDefaultProps</code> seems to be used at other points in the component lifecycle -- not just in the constructor. For example, if I inspect what gets sent to <code class="notranslate">componentWillReceiveProps(props)</code>, I can see that the default props are applied.</p>
<p dir="auto">This <em>doesn't</em> seem to be the case when using the ES6 class syntax, which means I have to duplicate code. Here's an example of what I mean:</p>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="class Control extends React.Component {

  constructor(props) {
    props.value = props.value || '';
    super(props);
  }

  // ...

  componentWillReceiveProps(props) {
    props.value = props.value || '';
    // Do something with props...
  }

}"><pre class="notranslate"><span class="pl-k">class</span> <span class="pl-v">Control</span> <span class="pl-k">extends</span> <span class="pl-v">React</span><span class="pl-kos">.</span><span class="pl-c1">Component</span> <span class="pl-kos">{</span>

  <span class="pl-en">constructor</span><span class="pl-kos">(</span><span class="pl-s1">props</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-s1">props</span><span class="pl-kos">.</span><span class="pl-c1">value</span> <span class="pl-c1">=</span> <span class="pl-s1">props</span><span class="pl-kos">.</span><span class="pl-c1">value</span> <span class="pl-c1">||</span> <span class="pl-s">''</span><span class="pl-kos">;</span>
    <span class="pl-smi">super</span><span class="pl-kos">(</span><span class="pl-s1">props</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
  <span class="pl-kos">}</span>

  <span class="pl-c">// ...</span>

  <span class="pl-en">componentWillReceiveProps</span><span class="pl-kos">(</span><span class="pl-s1">props</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-s1">props</span><span class="pl-kos">.</span><span class="pl-c1">value</span> <span class="pl-c1">=</span> <span class="pl-s1">props</span><span class="pl-kos">.</span><span class="pl-c1">value</span> <span class="pl-c1">||</span> <span class="pl-s">''</span><span class="pl-kos">;</span>
    <span class="pl-c">// Do something with props...</span>
  <span class="pl-kos">}</span>

<span class="pl-kos">}</span></pre></div>
<p dir="auto">As you can see, I'm duplicating the expression <code class="notranslate">props.value = props.value || ''</code>. If I had more than one default, I'd obviously have a lot more duplication.</p>
<p dir="auto">When using the <code class="notranslate">.createClass</code> method, I could return <code class="notranslate">{value: ''}</code> from the <code class="notranslate">getDefaultProps</code> method, and this would work, and I'd only have to do it once.</p>
<p dir="auto">Does it make sense to restore this method to avoid unnecessary duplication? Is there another, more React-like approach that I'm not aware of?</p>
<p dir="auto">With other higher-order/wrapper components from other libraries, I can replace a component with a wrapped version of itself like this:</p>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="let Component = () =&gt; &lt;div&gt;hello world&lt;/div&gt;;

// connect from react-redux
Component = connect(selector)(Component);
// withRouter from react-router
Component = withRouter(Component);

export default Component;"><pre class="notranslate"><span class="pl-k">let</span> <span class="pl-v">Component</span> <span class="pl-c1">=</span> <span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-c1">&lt;</span><span class="pl-ent">div</span><span class="pl-c1">&gt;</span>hello world<span class="pl-c1">&lt;</span><span class="pl-c1">/</span><span class="pl-ent">div</span><span class="pl-c1">&gt;</span><span class="pl-kos">;</span>

<span class="pl-c">// connect from react-redux</span>
<span class="pl-v">Component</span> <span class="pl-c1">=</span> <span class="pl-en">connect</span><span class="pl-kos">(</span><span class="pl-s1">selector</span><span class="pl-kos">)</span><span class="pl-kos">(</span><span class="pl-v">Component</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-c">// withRouter from react-router</span>
<span class="pl-v">Component</span> <span class="pl-c1">=</span> <span class="pl-en">withRouter</span><span class="pl-kos">(</span><span class="pl-v">Component</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-k">export</span> <span class="pl-k">default</span> <span class="pl-v">Component</span><span class="pl-kos">;</span></pre></div>
<p dir="auto">I don't see a lot of people do it this way, so I guess it's not recommended best practice. I know mutating is the devil and functional is always the way to go, but I think this is a lot cleaner because, 1) you don't have to nest a bunch of functions which increases the indent of the code and decreases readability, 2) you don't have to create a bunch of separate duplicate component names with obtuse names like <code class="notranslate">ComponentWithRouter</code> or <code class="notranslate">ConnectedComponentWithRouterWithForwardedRef</code>, and 3) your first definition of the component is just the pure display component that receives all the props it needs (it doesn't care where they come from), and then you define everything that "connects" to it separately.</p>
<p dir="auto">Anyway, with <code class="notranslate">forwardRef</code>, reassigning the component like this seems to crash React.</p>
<p dir="auto"><strong>Fine:</strong></p>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="const UnforwardedComponent = ({ forwardedRef,  ...props}) =&gt; &lt;div&gt;sup&lt;/div&gt;
const Component = forwardRef((props, ref) =&gt; &lt;UnforwardedComponent {...props} forwardedRef={ref} /&gt;;
export default Component;"><pre class="notranslate"><span class="pl-k">const</span> <span class="pl-v">UnforwardedComponent</span> <span class="pl-c1">=</span> <span class="pl-kos">(</span><span class="pl-kos">{</span> forwardedRef<span class="pl-kos">,</span>  ...<span class="pl-s1">props</span><span class="pl-kos">}</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-c1">&lt;</span><span class="pl-ent">div</span><span class="pl-c1">&gt;</span>sup<span class="pl-c1">&lt;</span><span class="pl-c1">/</span><span class="pl-ent">div</span><span class="pl-c1">&gt;</span>
<span class="pl-k">const</span> <span class="pl-v">Component</span> <span class="pl-c1">=</span> <span class="pl-en">forwardRef</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-s1">props</span><span class="pl-kos">,</span> <span class="pl-s1">ref</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-c1">&lt;</span><span class="pl-v">UnforwardedComponent</span> <span class="pl-kos">{</span>...<span class="pl-s1">props</span><span class="pl-kos">}</span> <span class="pl-c1">forwardedRef</span><span class="pl-c1">=</span><span class="pl-kos">{</span><span class="pl-s1">ref</span><span class="pl-kos">}</span> <span class="pl-c1">/</span><span class="pl-c1">&gt;</span><span class="pl-kos"></span><span class="pl-kos">;</span>
<span class="pl-k">export</span> <span class="pl-k">default</span> <span class="pl-v">Component</span><span class="pl-kos">;</span></pre></div>
<p dir="auto"><strong>Also fine:</strong></p>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="const Component = forwardRef((props, ref) =&gt; &lt;div {...props} ref={ref}&gt;sup&lt;/div&gt;;
export default Component;"><pre class="notranslate"><span class="pl-k">const</span> <span class="pl-v">Component</span> <span class="pl-c1">=</span> <span class="pl-en">forwardRef</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-s1">props</span><span class="pl-kos">,</span> <span class="pl-s1">ref</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-c1">&lt;</span><span class="pl-ent">div</span> <span class="pl-kos">{</span>...<span class="pl-s1">props</span><span class="pl-kos">}</span> <span class="pl-c1">ref</span><span class="pl-c1">=</span><span class="pl-kos">{</span><span class="pl-s1">ref</span><span class="pl-kos">}</span><span class="pl-c1">&gt;</span>sup<span class="pl-c1">&lt;</span><span class="pl-c1">/</span><span class="pl-ent">div</span><span class="pl-c1">&gt;</span><span class="pl-kos"></span><span class="pl-kos">;</span>
<span class="pl-k">export</span> <span class="pl-k">default</span> <span class="pl-v">Component</span><span class="pl-kos">;</span></pre></div>
<p dir="auto"><strong>Crashes:</strong></p>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="let Component = ({ forwardedRef, ...props }) =&gt; &lt;div&gt;sup&lt;/div&gt;;
Component = forwardRef((props, ref) =&gt; &lt;Component {...props} forwardedRef={ref} /&gt;
export default Component;"><pre class="notranslate"><span class="pl-k">let</span> <span class="pl-v">Component</span> <span class="pl-c1">=</span> <span class="pl-kos">(</span><span class="pl-kos">{</span> forwardedRef<span class="pl-kos">,</span> ...<span class="pl-s1">props</span> <span class="pl-kos">}</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-c1">&lt;</span><span class="pl-ent">div</span><span class="pl-c1">&gt;</span>sup<span class="pl-c1">&lt;</span><span class="pl-c1">/</span><span class="pl-ent">div</span><span class="pl-c1">&gt;</span><span class="pl-kos">;</span>
<span class="pl-v">Component</span> <span class="pl-c1">=</span> <span class="pl-s1">forwardRef</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-s1">props</span><span class="pl-kos">,</span> <span class="pl-s1">ref</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-c1">&lt;</span><span class="pl-v">Component</span> <span class="pl-kos">{</span>...<span class="pl-s1">props</span><span class="pl-kos">}</span> <span class="pl-c1">forwardedRef</span><span class="pl-c1">=</span><span class="pl-kos">{</span><span class="pl-s1">ref</span><span class="pl-kos">}</span> <span class="pl-c1">/</span><span class="pl-c1">&gt;</span>
<span class="pl-s1">export</span> <span class="pl-k">default</span> <span class="pl-v">Component</span><span class="pl-kos">;</span></pre></div>
<p dir="auto">I assume there's a under-the-hood reason why this doesn't work. But if it's at all possible, it'd be great to allow <code class="notranslate">forwardRef</code> to work in this manner.</p>
<p dir="auto">Please let me know if I'm missing something obvious.</p>