title: How to make pure, generic React components with immutable data that needs to be transformed
body: <p><em>Please also help me with the title and to express the problem better.</em></p>
  
  <p>I've met a problem in my react/redux architecture that I can't find many examples on.</p>
  
  <p>My application relies on immutability, reference equality and <code>PureRenderMixin</code> for performance. But I find it hard to create more generic and reusable components with such architecture.</p>
  
  <p>Lets say I have a generic <code>ListView</code> like this:</p>
  
  <pre class="lang-js prettyprint-override"><code>const ListView = React.createClass({
      mixins: [PureRenderMixin],
  
      propTypes: {
          items: arrayOf(shape({
              icon: string.isRequired,
              title: string.isRequired,
              description: string.isRequired,
          })).isRequired,
      },
  
      render() {
          return (
              &lt;ul&gt;
                  {this.props.items.map((item, idx) =&gt; (
                      &lt;li key={idx}&gt;
                          &lt;img src={item.icon} /&gt;
                          &lt;h3&gt;{item.title}&lt;/h3&gt;
                          &lt;p&gt;{item.description}&lt;/p&gt;
                      &lt;/li&gt;
                  )}
              &lt;/ul&gt;
          );
      },
  });
  </code></pre>
  
  <p>And then I want to use the list view to display users from a redux store. They have this structure:</p>
  
  <pre class="lang-js prettyprint-override"><code>const usersList = [
      { name: 'John Appleseed', age: 18, avatar: 'generic-user.png' },
      { name: 'Kate Example', age: 32, avatar: 'kate.png' },
  ];
  </code></pre>
  
  <p>This is a very normal senario in my applications so far. I usually render it like:</p>
  
  <pre class="lang-js prettyprint-override"><code>&lt;ListView items={usersList.map(user =&gt; ({
      title: user.name,
      icon: user.avatar,
      description: `Age: ${user.age}`,
  }))} /&gt;
  </code></pre>
  
  <p>Problem is that <code>map</code> breaks the reference equality. The result of
  <code>usersList.map(...)</code> will always be new list objects. So even when <code>usersList</code> hasn't changed since previous render, the <code>ListView</code> can't know that it still has a equal <code>items</code>-list.</p>
  
  <p>I can see three solutions to this, but I don't like them very good.</p>
  
  <p><strong>Solution 1: Pass a <code>transformItem</code>-function as a parameter and let <code>items</code> be an array of raw objects</strong></p>
  
  <pre class="lang-js prettyprint-override"><code>const ListView = React.createClass({
      mixins: [PureRenderMixin],
  
      propTypes: {
          items: arrayOf(object).isRequired,
          transformItem: func,
      },
  
      getDefaultProps() {
          return {
              transformItem: item =&gt; item,
          }
      },
  
      render() {
          return (
              &lt;ul&gt;
                  {this.props.items.map((item, idx) =&gt; {
                      const transformedItem = this.props.transformItem(item);
  
                      return (
                          &lt;li key={idx}&gt;
                              &lt;img src={transformedItem.icon} /&gt;
                              &lt;h3&gt;{transformedItem.title}&lt;/h3&gt;
                              &lt;p&gt;{transformedItem.description}&lt;/p&gt;
                          &lt;/li&gt;
                      );
                  })}
              &lt;/ul&gt;
          );
      },
  });
  </code></pre>
  
  <p>This will work very well. I can then render my user list like this:</p>
  
  <pre class="lang-js prettyprint-override"><code>&lt;ListView
      items={usersList}
      transformItem={user =&gt; ({
          title: user.name,
          icon: user.avatar,
          description: `Age: ${user.age}`,
      })}
  /&gt;
  </code></pre>
  
  <p>And the ListView will only rerender when <code>usersList</code> changes. But I lost the prop type validation on the way.</p>
  
  <p><strong>Solution 2: Make a specialized component that wraps the <code>ListView</code>:</strong></p>
  
  <pre class="lang-js prettyprint-override"><code>const UsersList = React.createClass({
      mixins: [PureRenderMixin],
  
      propTypes: {
          items: arrayOf(shape({
              name: string.isRequired,
              avatar: string.isRequired,
              age: number.isRequired,
          })),
      },
  
      render() {
          return (
              &lt;ListView
                  items={this.props.items.map(user =&gt; ({
                      title: user.name,
                      icon: user.avatar,
                      description: user.age,
                  }))}
              /&gt;
          );
      }
  });
  </code></pre>
  
  <p>But that is a lot more code! Would be better if I could use a stateless component, but I haven't figured out if they works like normal components with <code>PureRenderMixin</code>. (stateless components is sadly still an undocumented feature of react)</p>
  
  <pre class="lang-js prettyprint-override"><code>const UsersList = ({ users }) =&gt; (
      &lt;ListView
          items={users.map(user =&gt; ({
              title: user.name,
              icon: user.avatar,
              description: user.age,
          }))}
      /&gt;
  );
  </code></pre>
  
  <p><strong>Solution 3: Create a generic pure transforming component</strong></p>
  
  <pre class="lang-js prettyprint-override"><code>const ParameterTransformer = React.createClass({
      mixin: [PureRenderMixin],
  
      propTypes: {
          component: object.isRequired,
          transformers: arrayOf(func).isRequired,
      },
  
      render() {
          let transformed = {};
  
          this.props.transformers.forEach((transformer, propName) =&gt; {
              transformed[propName] = transformer(this.props[propName]);
          });
  
          return (
              &lt;this.props.component
                  {...this.props}
                  {...transformed}
              &gt;
                  {this.props.children}
              &lt;/this.props.component&gt;
          );
      }
  });
  </code></pre>
  
  <p>and use it like</p>
  
  <pre class="lang-js prettyprint-override"><code>&lt;ParameterTransformer
      component={ListView}
      items={usersList}
      transformers={{
          items: user =&gt; ({
              title: user.name,
              icon: user.avatar,
              description: `Age: ${user.age}`,
          })
      }}
  /&gt;
  </code></pre>
  
  <p><strong>Are these the only solutions, or have I missed something?</strong></p>
  
  <p>None of these solutions fits very well with the component I'm currently working on. Number one fits best, but I feel like if that is the track I choose to go on, then all kinds of generic components I make should have these <code>transform</code> properties. And also it is a major downside that I can't use React prop type validation when creating such components.</p>
  
  <p>Solution 2 is probably the most semantic correct, at least for this <code>ListView</code> example. But I think it is very verbose, and also it doesn't fit very well with my real usecase.</p>
  
  <p>Solution 3 is just too magic and unreadable.</p>