Add fresh inline designs to a React high-order component creation

Applying a common HOC pattern like this can be quite effective. However, there are instances where you may not want a component to be wrapped, but rather just extended. This is the challenge I am facing here.

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);

In the following examples, a button is rendered without any style attributes.

Example 1.1: pass-through via createClass

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

Example 1.2 pass-through via direct render

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

Example 2: create

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

Example 3: clone

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

Based on some insights gathered online, it appears challenging to return the same Component if it is the only child.

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

Answer №1

When creating a button without any style attributes, remember to pass along the style prop.

Could the issue be resolved by modifying the code like this:

const CustomButton = (props) => <button style={props.style}>{props.text}</button>

Update:

It's important to note that Higher Order Components (HOCs) don't automatically pass props to children of the wrapped component. This means that basic elements like <button /> or <div /> require props to be explicitly provided. While you're passing props to <CustomButton />, not to <button />. You can, however, create an HOC that enhances a basic element.

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

Usage:

let EnhancedButton = enhanceElement('button')

let MainApp = props => <EnhancedButton>{props.text}</EnhancedButton>

Example

Incorporating known props like style and className when creating components can enhance reusability without specifying implementation details.

// Best practice!
let StyledButton = ({ children, ...props }) => <button {...props}>{children}</button>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

JavaScript maintain a variable that holds onto nodes even after they have been removed

Recently, I encountered a seemingly simple issue with JavaScript that has me stumped. In my code, I have a variable that stores nodes with a specific class. My goal is to remove these nodes from the DOM while still retaining them in the variable. However, ...

I am in search of a container that has full height, along with unique footer and content characteristics

I have set up a jsfiddle to demonstrate the scenario I am facing: There is a basic header, content, footer layout. Within the content-container is a messenger that should expand to a maximum of 100% height. Beyond 100% height, it should become scrollable. ...

Executing a Databind function using the keypress method in jQuery

On my simple page, I have a repeater being populated by a C# databind method. The page includes a search textbox that performs real-time searching as you type. This functionality is achieved by utilizing the rowfilter in the databind method to filter the r ...

What criteria do browsers follow to determine the specific colors to use for border styles like inset and outset?

When I set border: 1px outset blue; as the style for an element, the browser displays two distinct border colors: one for the top and left borders, and another for the bottom and right borders. li { border: 10px outset #0000FF; color: #FFF; ...

Fulfill the promise in AngularJS and assign it to a different factory

Presenting my factory below: .factory('UserData', ['User', '$q', function(User, $q) { var deferred = $q.defer(); return { user: null, get: function() { var _this = this; _this. ...

Executing multiple Ajax requests on CodeIgniter 3 from two separate pages

I am facing a critical need for a code review and unfortunately, I am unsure of where else to seek assistance besides here. Let me outline my current task: I am working on a user profile page that is designed to showcase users' comments. Users have t ...

"Utilizing a Font Awesome icon within the dropdown list of a combobox in Ext JS

I have attempted multiple methods to add an icon in the displayfield when a combo box item is selected without success. Here is the fiddle link for anyone who would like to help me with this issue. Your assistance is greatly appreciated. View the example ...

Is there a way to ensure a Javascript alert appears just one time and never again?

I struggle with Javascript, but I have a specific task that needs to be completed. I am participating in a school competition and need an alert to appear only once throughout the entire project, not just once per browsing session. The alert will inform ...

Angular select element is not functioning properly with the `addEventListener` method

My current project involves creating a table using the primeng library. The table consists of three rows and three columns, and all the data is static. Even though I am utilizing an external library, I find myself traversing the DOM directly. <p-table ...

Using JQuery to reveal a hidden child element within a parent element

I'm facing a challenge with displaying nested ul lists on my website. The parent ul is hidden with CSS, causing the child ul to also remain hidden even when I try to display it using jQuery. One approach I've attempted is adding a class to the f ...

Flexible columns with dynamic maximum width based on percentage

After extensive research, I am turning to stackoverflow for help with a seemingly simple task that has proven difficult to achieve. I have three columns of expandable content and need them to adjust in size proportionally when one or more are expanded. Eac ...

What is the best way to horizontally center items within an unordered list (ul li) inside a div class

I'm attempting to center a horizontal lineup of small icons. In the Launchrock platform, users have the ability to customize all code. Unfortunately, I do not have access to their default CSS, but we are able to override it. <div class="LR-site-co ...

Issues arise with AngularJS showing images fetched from an API

Currently, I am facing an issue where I am trying to display images from a REST API but keep receiving a "error 403" message. Here is the link to my JSFiddle. Please take a look, as I have attempted using both <img src=""> and ng-src='', bu ...

Creating an ongoing loop endlessly using recursion in node.js

Seeking assistance in creating a recursive loop to continuously iterate through functions in Node.js for flow control. I have tried online tutorials but still struggling to comprehend it fully. Can anyone provide guidance or point me towards a proper tutor ...

Canvas image zoom and crop feature ensures fixed selection area across all platforms

After finding inspiration from a source I cannot name, I developed a plugin that allows for image cropping on both mobile and desktop devices. The key features of my plugin include touch support, dynamic canvas sizing based on image dimensions, and the ab ...

Is the for loop in Node.js completed when making a MySQL call?

A certain function passes an array named res that contains user data in the following format: [ RowDataPacket { UserID: 26 }, RowDataPacker { UserID: 4 } ] The goal is to create a function that fetches each user's username based on their ID and stor ...

Loading jQuery on document ready with an Ajax request can lead to slow loading times

My current project involves a significant number of ajax requests being made on document.ready. Additionally, I have ajax requests for every database transaction. These requests are all managed in a JS file, with each ajax request corresponding to a PHP pa ...

What is the best way to align text with my CSS number and circle on the same line?

Here are two questions for you: First off, I've successfully created a circle with a number inside it using CSS. How can I go about filling the circle with color? Secondly, I'd like to know how I can align the words "Opportunity #1" on the same ...

How can I make tooltipster display tooltips properly?

I have been struggling to customize tooltips using a library called tooltipster. Here is what I currently have: Head of index.html: <head> <!--TOOLTIP CSS--> <link rel="stylesheet" type="type/css" href="node_modules/tooltipster-master ...

Ways in which breakpoint.value can be utilized?

I've created a platform to manage employee activities, and I want it to be fully responsive across all devices. For instance, if you wish to tailor the site for screens labeled as "sm" and "xs," you can use the following code: [theme.breakpoints.down ...