Search code examples
javascriptreactjsdesign-patternsreduxpurely-functional

What is a robust way of rendering a dynamic quantity of React child components, using the Redux container component pattern?


Say I have a functional React presentation component, like so:

const Functional = (props) => {
  // do some stuff

  return (
    <div>
      // more HTML based on the props
    </div>
  );
}

Functional.propTypes = {
  prop1: React.PropTypes.string.isRequired,
  prop2: React.PropTypes.string.isRequired,
  // ...
};

If I'm using Redux and following the container component pattern, what would be the best way to render a dynamic number of these <Functional/> components inside a wrapper component, based on elements inside a array (which is inside my Redux state)?

E.g. My Redux state might look like this:

{
  functionalItems: [
    {
      prop1: 'x1',
      prop2: 'y1',
      // ...
    },
    {
      prop1: 'x2',
      prop2: 'y2'
    },
    // ... more items
  ],
  // ...
}

So each item in the functionalItems array should correspond to a <Functional/> component, which all get rendered adjacent to each other.

This is the second time I have come across this problem, so I'm hoping that it's common enough that there is good solution out there.

I'll post the solutions I can come up with (but which have undesirable traits), as answers to this question.


Solution

  • I'd like to suggest that you pass the entire array to the wrapper component like this:

    const mapStateToProps = (state) => ({
        items: getFunctionalItems(state),
        // ...
    });
    

    and then in your Wrapper.jsx, do it like this:

    const Wrapper = (props) => {
    
      const elements = props.items.map((item, index) => {
        <Functional prop1={ item.prop1 } prop2={ item.prop2 } ...
          key={ ... /* you can use index here */ }/>
      });
    
      return (
        <div>
          { elements }
        </div>
      );
    
    };
    

    ...where getFunctionalItems() is an accessor function that is the canonical means of accessing the functional items from the state.

    This way, you can handle changes in state structure, or a different rendering layout. (ergo more robust (I think)). And it looks more like following the Single Responsibility Principle.