0
\$\begingroup\$

I have two React components. The only difference is the input tag vs select tag. I'm trying to move the bulk of the duplicate code to a higher order component but I can't wrap my head around it. Any suggestions?

import React from "react";
import Style from "./style.scss";

export class FloatingLabelInput extends React.Component {
    render() {
        const { label, ...props } = this.props;
        const clsOK = props.value ? Style.ok : "";
        return (
            <div className={`${Style.wrapper}`}>
                <input className={`${Style.input} ${clsOK}`} ref={el => this.input = el} {...props} />
                <label className={`${Style.label}`} htmlFor={props.id}>{label}</label>
            </div>
        );
    }
}

export class FloatingLabelDropDown extends React.Component {
    render() {
        const { label, ...props } = this.props;
        const clsOK = props.value ? Style.ok : "";
        return (
            <div className={`${Style.wrapper}`}>
                <select
                    className={`${Style.input} ${clsOK}`}
                    ref={el => this.input = el} {...props} >
                    {this.props.children}
                </select>
                <label className={`${Style.label}`} htmlFor={props.id}>{label}</label>
            </div>
        );
    }
}
\$\endgroup\$
0
\$\begingroup\$

I think I have an understanding of what you are trying to do, but because select has children and and input does not it's a little tricky but this is what I came up with:

import React, { Component } from 'react'
import { render } from 'react-dom'

class FloatingLabel extends Component {
  render() {
    return (
      <div>
        <this.props.render option='Hello'  />
      </div>
    )
  }
}

class SelectDropDown extends Component {
  render() {
    return (
      <select>
        <option>{this.props.option}</option>
      </select>
    )
  }
}

class InputDropDown extends Component {
  render() {
    return (
      <input />
    )
  }
}


render(<FloatingLabel render={SelectDropDown} />, document.querySelector('#root'))

In this example you can create a <FloatingLabel /> component that can either take a SelectDropDown or a InputDropDown component as a prop. You can then render that prop in the FloatingLabel parent and pass whatever props that you need to pass down to the children.

Basically what you would be changing is the everything inside the div except for the label.

\$\endgroup\$
  • \$\begingroup\$ I think you've got me on the right path. The missing piece of the puzzle was passing the child component as a prop. \$\endgroup\$ – Chris May 29 '17 at 10:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.