首页 > 解决方案 > 如何将一个函数作为参数传递给另一个通过 React 列表映射的函数?

问题描述

我正在尝试创建一个除了映射列表之外什么都不做的函数。此功能始终相同,但列表项字段(Fields)可以更改。所以我试图将字段传递给映射函数,以便我可以重用映射函数(列表和项目)并且只更改字段。

这是我编写的代码示例。它按原样工作,但我不知道如何将 map 函数存储在其他可以在多个相似组件之间重用的地方。

const Fields = (props) => {
  return (
    <Fragment>      
      <MediaGroup { ...props } />
      <TextRich   { ...props } /> 
      <LinkGroup  { ...props } />
    </Fragment>
  );
}

const Item = (props) => {
  return (
    <PanelBody title={ `Item ${props.index + 1}` } initialOpen={ false }>
      <PanelRow>
        <RmListItemMarkup { ...props } />
        <Fields           { ...props } />
      </PanelRow>
    </PanelBody>
  );
}

export const List = (props) => {
  const { attr } = props;
  return (
    <Fragment>
      <PanelBody title={ __('Content List') } initialOpen={ true }>
        <AddListItemMarkup { ...props } />
      </PanelBody>

      { (attr && attr.length) ? attr.map((item, index) => <Item key={ index } index={ index } { ...props } />) : null }
    </Fragment>
  );  
}

理想情况下,我希望 List 和 Item 拥有自己的文件,并简单地从包含 Fields 的文件中导入它们。这样我就可以自定义 Fields 并传递给 List,而不必在同一个文件中重复 List 和 Item。事实上,从技术上讲,List 和 Item 可以是同一个函数,我需要传递的只是 Fields。

请让我知道您是否知道任何解决方案。提前致谢!

标签: reactjs

解决方案


一种方法是使用 HOC:

const ItemType1 = (props) => (
  <div>
    <div>item type 1</div>
    <pre>{JSON.stringify(props, undefined, 2)}</pre>
  </div>
);
const ItemType2 = (props) => (
  <div>
    <div>item type 2</div>
    <pre>{JSON.stringify(props, undefined, 2)}</pre>
  </div>
);
const ItemHoc = (ItemType) => (props) => (
  <ItemType {...props} />
);
const ListHoc = (Item) => ({ items }) => (
  <ul>
    {items.map((item, index) => (
      <Item key={index} item={item} />
    ))}
  </ul>
);
const Type1List = ListHoc(ItemHoc(ItemType1));
const Type2List = ListHoc(ItemHoc(ItemType2));
const App = () => {
  const items = [1, 2, 3];
  return (
    <div>
      <Type1List items={items} />
      <Type2List items={items} />
    </div>
  );
};
ReactDOM.render(<App />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>


<div id="root"></div>

另一种方法是渲染道具:

const ItemType1 = (props) => (
  <div>
    <div>item type 1</div>
    <pre>{JSON.stringify(props, undefined, 2)}</pre>
  </div>
);
const ItemType2 = (props) => (
  <div>
    <div>item type 2</div>
    <pre>{JSON.stringify(props, undefined, 2)}</pre>
  </div>
);
const Item = ({ Render, ...props }) => (
  <Render {...props} />
);
const List = ({ items, ...props }) => (
  <ul>
    {items.map((item, index) => (
      <Item key={index} item={item} {...props} />
    ))}
  </ul>
);
const App = () => {
  const items = [1, 2, 3];
  return (
    <div>
      <List items={items} Render={ItemType1} />
      <List items={items} Render={ItemType2} />
    </div>
  );
};
ReactDOM.render(<App />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>


<div id="root"></div>


推荐阅读