为React HOC产品注入新的内联样式

时间:2016-10-26 20:49:39

标签: javascript css reactjs

使用像这样的普通HOC模式可以很好地工作。但是,有时候你真的不想要一个组件被包装,只是希望你传入的相同组件有点扩展。这就是我在这里挣扎的事情。

Wrapper 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

1 个答案:

答案 0 :(得分:1)

  

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

这不是因为你没有通过风格道具吗?这样做不会解决这个问题:

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

更新

HOC不会神奇地将道具应用于包裹组件的子项,这意味着像<button /><div />这样的低级元素需要以这种或那种方式传递给它们的道具。您将道具传递给<Button />,而不是<button />。但是,您可以创建一个带有基本元素的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>