简体   繁体   English

如何在React中处理两个相似的组件

[英]How to handle two similar components in react

I am very new to React. 我对React非常陌生。 I have two components: TimePickerComponent and the TimeDurationPickerComponent. 我有两个组件:TimePickerComponent和TimeDurationPickerComponent。

The TimePickerComponent gets passed a TimeString(string) via props(only if initial data exists) and displays it like "08:00". TimePickerComponent通过props(仅当存在初始数据时)传递了TimeString(string),并显示为“ 08:00”。 Code: 码:

class TimePickerComponent extends React.Component {
    _placeholder;
    _defaultTimeString;
    _timeString;
    _errorStatus;
    _classes;

    constructor({ placeholder, defaultTimeString, timeString, errorStatus, classes }) {
        super();
        this._placeholder = placeholder;
        this._defaultTimeString = defaultTimeString;
        this._timeString = timeString;
        this._errorStatus = errorStatus;
        this._classes = classes;
    }

    get Placeholder() {
        return this._placeholder;
    }

    get DefaultTimeString() {
        return this._defaultTimeString ? this._defaultTimeString : CONTROLS_CONSTANTS.DEFAULT_TIME_STRING;
    }

    get TimeString() {
        return this._timeString;
    }

    get ErrorStatus() {
        return this._errorStatus;
    }

    get Classes() {
        return this._classes;
    }

    render() {
        return <FormControl>
            <TextField error={this.ErrorStatus}
                label={this.Placeholder}
                defaultValue={this.TimeString ? this.TimeString : this.DefaultTimeString}
                className={this.Classes.layout}
                type="time"
                InputLabelProps={{
                    shrink: true
                }}
            />
        </FormControl>
    }
}

TimePickerComponent.propTypes = {
    placeholder: PropTypes.string.isRequired,
    defaultTimeString: PropTypes.string,
    timeString: PropTypes.string,
    errorStatus: PropTypes.bool
}

export default withStyles(styles)(TimePickerComponent);

The TimeDurationPickerComponent gets passed a TimeInMinutes(number) via props. 通过道具将TimeDurationPickerComponent传递给TimeInMinutes(number)。 But the display is the same as of the TimePickerComponent("08:00"). 但是显示与TimePickerComponent(“ 08:00”)相同。 Code: 码:

class TimeDurationPickerComponent extends React.Component {
    _placeholder;
    _timeInMinutes;
    _classes;

    constructor({ placeholder, timeInMinutes, classes }) {
        super();
        this._placeholder = placeholder;
        this._timeInMinutes = timeInMinutes;
        this._classes = classes;
    }

    get Placeholder() {
        return this._placeholder;
    }

    get TimeInMinutes() {
        return this._timeInMinutes;
    }

    get Classes() {
        return this._classes;
    }

    get TimeString() {
        let timeFormat = CONTROLS_CONSTANTS.TIME_FORMATS.HOURS_MINUTES_COLON_SEPARATED;
        let duration = moment.duration({ minutes: this.TimeInMinutes });

        //https://github.com/moment/moment/issues/463
        return moment.utc(duration.asMilliseconds()).format(timeFormat);
    }

    render() {
        return <TimePickerComponent
            placeholder={this.Placeholder}
            timeString={this.TimeString}
            classes={this.Classes}
        />
    }
}

TimeDurationPickerComponent.propTypes = {
    placeholder: PropTypes.string.isRequired,
    timeInMinutes: PropTypes.number
}

export default TimeDurationPickerComponent;

To avoid code redundancy I reused my TimePickerComponent in the TimeDurationPickerComponent and just convert the TimeInMinutes in a TimeString and pass it down to the TimePickerComponent via props. 为了避免代码冗余,我在TimeDurationPickerComponent中重用了TimePickerComponent,只是将TimeInMinutes转换为TimeString并将其通过props传递给TimePickerComponent。

My question now : Is this a good practice how I solved this or should I use a HigherOrderComponent for that? 现在我的问题是 :这是解决该问题的一种好习惯,还是应该为此使用HigherOrderComponent? Or should I use an inheritance approach for that? 还是我应该使用继承方法? Which solution would be the best and why? 哪种解决方案是最好的,为什么?

Thank you in advance. 先感谢您。

What you've done here is probably fine. 您在这里所做的可能很好。 It could be done with a higher order component as well but a composition based approach like what you have won't have any performance issues and to be honest it's probably more readable than using an HOC. 也可以使用更高阶的组件来完成,但是基于构图的方法(例如您所拥有的方法)不会出现任何性能问题,并且说实话,与使用HOC相比,它可能更具可读性。

On another note you should be using this.props and this.state to represent your class properties. 另一方面,您应该使用this.props和this.state表示您的类属性。 They are build into React components and are what will cause your component to automatically re-render upon change. 它们内置在React组件中,它们会导致您的组件在更改后自动重新呈现。

It also makes your code significantly more concise so for example you could reduce your second component down to something like this: 这也使您的代码更加简洁,例如,您可以将第二个组件缩减为以下形式:

class TimeDurationPickerComponent extends React.Component {

    constructor(props) {
        super(props);
    }

    createTimeString() {
        let timeFormat = CONTROLS_CONSTANTS.TIME_FORMATS.HOURS_MINUTES_COLON_SEPARATED;
        let duration = moment.duration({ minutes: this.props.TimeInMinutes });

        //https://github.com/moment/moment/issues/463
        return moment.utc(duration.asMilliseconds()).format(timeFormat);
    }

    render() {
        return <TimePickerComponent
            placeholder={this.props.Placeholder}
            timeString={this.createTimeString()}
            classes={this.props.Classes}
        />
    }
}

Example of a component that uses flow: 使用流程的组件示例:

// @flow

import React from 'react';

import './css/ToggleButton.css';

type Props = {
  handleClick: Function;
  label: string;
};

type LocalState = {
  active: bool,
};

class ToggleButton extends React.Component<Props, LocalState> {
  clickHandler: () => void;

  constructor(props: Props) {
    super(props);

    this.state = {
      active: true,
    };

    this.clickHandler = this.clickHandler.bind(this);
  }

  clickHandler() {
    this.setState({ active: !this.state.active });
    this.props.handleClick();
  }

  render() {
    const buttonStyle = this.state.active ? 'toggle-btn-active' : 'toggle-btn-inactive';
    return (
      <button
        className={`toggle-btn ${buttonStyle}`}
        onClick={this.clickHandler}
      >{this.props.label}
      </button>
    );
  }
}

export default ToggleButton;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM