【问题标题】:Provide alternative render method for React Component为 React 组件提供替代渲染方法
【发布时间】:2019-05-11 14:24:33
【问题描述】:

在我的应用程序中,我有几个表单域组件,它们的行为方式都相同,但看起来略有不同。我希望能够使用单个表单域组件的状态和类方法,同时提供某种替代渲染方法,以便我可以即时自定义此元素的外观。我知道我可以包装孩子,然后在组件中使用props.children。但我希望以某种方式重用组件方法:

class Parent extends React.Component {
  render() {
    <div className="parent">
      <ChildFormField
        renderAlternate={self => {
          return (
            <div className="child--alternate">
              <input onChange={self.doThing} />
            </div>
          );
        }}
      />
    </div>
  }
}

// And the child component look something like...
class ChildFormField extends React.Component {
  state = {
    value: null
  }

  doThing = value => {
    return this.setState({ value });
  }

  render() {
    if (this.props.renderAlternate !== undefined) {
      return this.props.renderAlternate();
    }

    // standard return
    return <div />;
  }
}

除了基本用法之外,我对 React 还比较陌生。是否有推荐的方法来实现此功能?

【问题讨论】:

  • 关注的分离是这里的问题,你将JSX从父母传递给孩子,这里渲染你的孩子取决于你父母的JSX

标签: javascript reactjs components


【解决方案1】:

您的renderAlternate 函数需要一个参数self。所以调用的时候需要传递this

return this.props.renderAlternate(this);

请参阅 https://codesandbox.io/s/w759j6pl6k 作为您的代码示例。

【讨论】:

  • 啊,我什至认为这行不通。让我试试这个。如果视图中有 50-100 个这样的节点,您是否发现此方法存在任何扩展或性能问题?
  • @JLF 不是真的,这是一种叫做render props的模式
【解决方案2】:

这个食谱被称为render prop。它在合适的地方被广泛使用,但在这里它看起来像是糟糕的设计决策,主要是因为它的存在是为了访问组件self 实例。这是继承的情况:

class AlternateChildFormField extends ChildFormField {
  render() {
      return (
        <div className="child--alternate">
          <input onChange={this.doThing} />
        </div>
      );
  }
}

在 React 中,函数组合通常是首选,但如果它有良好的用途,继承是可接受的解决方案。 ChildFormField 要求 doThing 是一个方法而不是辅助函数,因为它需要访问 this.setState

另一种方法是使用 React 16.7 钩子和功能组件。这样同一个组件就可以用组合来表达:

const useThingState = () => {
  const [state, setState] = useState({ value: null });

  return value => {
    return setState({ value });
  };
}

const ChildFormField = props => {
  // not used here
  // const doThing = useThingState();

  return <div />;
}

const AlternateChildFormField =  props => {
  const doThing = useThingState();

  return (
    <div className="child--alternate">
      <input onChange={doThing} />
    </div>
  );
}

【讨论】:

  • 如果我有许多可重复的变化,这似乎是个好主意。但在大多数情况下,这些都需要在一次性情况下呈现变化。
  • 继承完全有效,一次性使用。尽管它在 React 生态系统中不受青睐,但它比 render prop 更合适 - 你已经知道组件可以扩展,所以你可以用 DRYest 方式设计它。而 16.7 的 hooks 对于那些在 React 领域中喜欢 FP 的人来说是合适的选择。
【解决方案3】:

在 React 生态系统中管理这种情况的常见方式是高阶组件:

参考:https://reactjs.org/docs/higher-order-components.html 参考:https://medium.com/backticks-tildes/reusing-react-component-logic-with-higher-order-component-3fbe284beec9

此外,您正在寻找的可能是状态逻辑的重用。

作为 React 16.7-alpha,您可以使用钩子将状态逻辑与功能组件重用,但 API 可能会发生重大变化。

参考:https://medium.com/@nicolaslopezj/reusing-logic-with-react-hooks-8e691f7352fa

【讨论】:

    猜你喜欢
    • 2016-06-17
    • 2017-01-25
    • 2016-08-07
    • 2012-05-12
    • 1970-01-01
    • 2018-12-08
    • 2021-05-10
    • 2018-11-15
    • 2020-12-12
    相关资源
    最近更新 更多