使用Redux容器组件模式渲染动态数量的React子组件的有效方法是什么?

时间:2017-01-09 03:12:02

标签: javascript reactjs design-patterns redux purely-functional

假设我有一个功能正常的React演示组件,如下所示:

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,
  // ...
};

如果我正在使用Redux并遵循容器组件模式,那么基于数组内部的元素(在内部)中,在包装器组件中呈现动态数量的这些<Functional/>组件的最佳方法是什么?我的Redux州?)

E.g。我的Redux状态可能如下所示:

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

因此,functionalItems数组中的每个项目都应对应一个<Functional/>组件,这些组件都会彼此相邻呈现。

这是我第二次遇到这个问题,所以我希望那里有很好的解决方案。

我会发布我能提出的解决方案(但有不良特征),作为这个问题的答案。

2 个答案:

答案 0 :(得分:1)

我想建议您将整个数组传递给包装器组件,如下所示:

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

然后在你的Wrapper.jsx中,按照以下方式执行操作:

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>
  );

};

...其中getFunctionalItems()是一个访问函数,它是从状态访问函数项的规范方法。

这样,您可以处理状态结构的更改或不同的呈现布局。 (ergo更健壮(我认为))。它看起来更像是遵循单一责任原则。

答案 1 :(得分:0)

解决方案描述

  • 创建一个包装函数表示组件,该组件接受数量和函数以获取<Functional/>道具值。
  • 创建一个连接到这个新包装器组件的容器组件,并传入数量(基于Redux状态)和访问器函数以获取<Functional/> prop值。

示例代码

Wrapper.jsx:

const Wrapper = (props) => {

  const elements = [];

  for (let i = 0; i < props.quantity; i++) {
    elements.push(
      <Functional prop1={ getPropValue1(i) } prop2={ getPropValue2(i) } ...
                  key={ ... }/>
    );
  }

  return (
    <div>
      { elements }
    </div>
  );
};

Wrapper.propTypes = {
  quantity: React.PropTypes.number.isRequired,
  getPropValue1: React.PropTypes.func.isRequired,
  getPropValue2: React.PropTypes.func.isRequired,
  // ...
};

ContainerComponent.js:

const mapStateToProps = (state) => ({
  quantity: state.functionalItems.length,
  getPropValue1: (index) => state.functionalItems[index].prop1,
  getPropValue2: (index) => state.functionalItems[index].prop2,
  // ...
});

const ContainerComponent = connect(mapStateToProps)(Wrapper);