首页 > 解决方案 > 具有相同状态/功能但 UI 不同的两个组件

问题描述

我有两个组件采用完全相同的道具并共享完全相同的方法。但他们有不同的用户界面。你会如何建议保持这个干燥?我的第一个想法:

  1. 创建一个具有 onClick 方法和 props/state 的 Wrapper 组件。
  2. 创建两个接受 props/state 的 UI 组件,然后根据需要进行渲染,例如:
<Wrapper>
  <UIComponent-1 />
</Wrapper>

<Wrapper>
  <UIComponent-2 />
</Wrapper>

有没有更好的方法来做到这一点?我正在考虑使包装器成为 HOC,但随后需要复制 onClick 功能(或从某个公共文件导入)。

标签: javascriptreactjs

解决方案


这是andy mccullough's answer的示例实现。

此示例创建一个组件,该组件包含一个可以通过调用reverse函数来反转的字符串。然后将 thevaluereversefunction 都提供给 render 属性。然后,您可以决定如何将函数附加到 DOM(如果有的话)以及值的显示位置和方式。

我还添加了一个默认render属性,但如果您没有默认场景,则可以将其省略。

提供给的函数render目前是匿名函数,但如果您想重用它们,可以将它们存储在变量中或导出它们。

const {Fragment, useState} = React;
const {Alert, Button} = ReactBootstrap;

const defaultRender = ({value, reverse}) => <span onClick={reverse}>{value}</span>;

function Reversible({initialValue = "", render: Render = defaultRender}) {
  const [value, setValue] = useState(initialValue);
  const reverse = () => setValue(value => value.split("").reverse().join(""));
  return <Render value={value} reverse={reverse} />;
};

ReactDOM.render(
  <Fragment>
    <Reversible initialValue="default render" />
    <Reversible
      initialValue="custom Alert render"
      render={({value, reverse}) => (
        <Alert variant="primary" onMouseEnter={reverse} onMouseOut={reverse}>
          {value}
        </Alert>
      )}
    />
    <Reversible
      initialValue="custom Button render"
      render={({value, reverse}) => (
        <Button onClick={reverse}>{value}</Button>
      )}
    />
  </Fragment>,
  document.getElementById("root")
);
<link rel="stylesheet" crossorigin="anonymous" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" />
<script crossorigin src="https://unpkg.com/react@16/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-bootstrap@next/dist/react-bootstrap.min.js"></script>

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


推荐阅读