【问题标题】:Inject new inline styles to a React HOC product为 React HOC 产品注入新的内联样式
【发布时间】:2016-11-04 04:46:47
【问题描述】:

像这样使用常见的 HOC 模式效果很好。但是,有时您真的不希望组件被包装,而只想扩展您传入的相同组件。这就是我在这里苦苦挣扎的地方。

包装器 HOC

const flexboxContainerStyles = {
  display: 'flex',
  flexDirection: 'row',
  backgroundColor: 'pink',
}

let WrapInFlexContainer = FlexChild => class extends React.Component {
  render(){

    return (
      <div className="flexContainer" style={flexboxContainerStyles} >
        <FlexChild {...this.props} />
      </div>
    )
  }
}

const Button = (props) => <button>{props.txt}</button>
let FlexButton = WrapInFlexContainer(Button);

以下示例生成一个没有样式属性的按钮。

示例 1.1:通过 createClass 传递

function hocPassThroughViaClass(Component) {
  return React.createClass({
    render: function() {
     return <Component {...this.props} style={flexboxContainerStyles}/>;
    }
  });
}

示例 1.2 通过直接渲染传递

let hocPassThroughViaRender = Element => class extends React.Component {
  render(){   
    return <Element {...this.props} className="flexContainer" style={flexboxContainerStyles} />
  }
}

示例 2:创建

function hocCreate(Component) {
  return React.createClass({
    render: function() {
      const modifiedProps = Object.assign({}, {...this.props}, {...flexboxContainerStyles});
      return React.createElement(Component, { ...modifiedProps });
    }
  });
}

示例 3:克隆

function hocClone(Component) {
  return React.createClass({
    render: function() {
      const modifiedProps = Object.assign({}, {...this.props}, {...flexboxContainerStyles});
      return React.cloneElement(<Component {...modifiedProps } />);
    }
  });
}

// render examples
let HOCPassThroughViaClassButton = hocPassThroughViaClass(Button); // 1.1
let HOCPassThroughRenderButton = hocPassThroughViaRender(Button); // 1.2 
let HOCCreatedButton = hocCreate(Button); // 2
let HOCClonedButton = hocClone(Button); // 3

从我在网络上到处看到的几点来看,如果它是独生子女,似乎不可能返回相同的 Component

见:https://github.com/threepointone/glamor/blob/master/docs/createElement.md

https://discuss.reactjs.org/t/trying-to-do-a-reactdom-render-a-el-replacing-the-el-not-appending-to-it/2681/2

【问题讨论】:

    标签: javascript css reactjs


    【解决方案1】:

    以下示例生成一个没有样式属性的按钮。

    这不是因为你没有传递 style 属性吗?这样做不会解决这个问题吗:

    const Button = (props) => <button style={props.style}>{props.txt}</button>
    

    更新:

    HOC 不会神奇地将 props 应用到包装组件的子组件,这意味着像 &lt;button /&gt;&lt;div /&gt; 这样的低级元素需要以一种或另一种方式传递给它们的 props。您将道具传递给&lt;Button /&gt;,而不是&lt;button /&gt;。但是,您可以制作一个采用基本元素并向其添加任何内容的 HOC。

    let hoc = element => (
      class extends React.Component {
        render() {
          let { children, ...props } = this.props
          return React.createElement(
            element, 
            { ...props, style: flexboxContainerStyles },
            children,
          )
        }
      }
    )
    

    用法:

    let FlexButton = hoc('button')
    
    let App = props => <FlexButton>{props.txt}</FlexButton>
    

    fiddle

    话虽如此,您并没有通过传递已知的属性(如 style 和 className)来更改基础组件的 API。事实上,这是一种让组件更可重用的好方法无需指定实现细节。

    // good!
    let Button = ({ children, ...props }) => <button {...props}>{children}</button>
    

    【讨论】:

    • 是的,但这违背了目的。目标是作为参数传递的组件不需要知道函数或更改自己的 API。
    • 更新了我的答案以解决您的评论。
    • 感谢您的详尽解释。
    • 经过一段时间的思考后,我注意到的一件事是,我觉得盲目地接受任何道具对象是一种代码味道。
    • 我当然同意。 a) 使用PropTypes,b) 传递“已知”的属性,例如样式、类名(DOM 元素可以实际使用的任何东西)
    猜你喜欢
    • 2020-10-20
    • 2017-06-15
    • 2013-07-30
    • 1970-01-01
    • 2014-05-29
    • 1970-01-01
    • 2017-07-19
    • 2018-07-04
    • 1970-01-01
    相关资源
    最近更新 更多