【问题标题】:Converting a stateful component to stateless将有状态组件转换为无状态组件
【发布时间】:2017-10-05 15:45:13
【问题描述】:

我对 react 和 redux 还很陌生,我在这里遇到了问题。每当需要状态处理时,必须仅将无状态组件与容器一起使用。这两个组件是:

import React from 'react';
import DatePicker from '../DatePicker';

class DayInput extends React.Component { // eslint-disable-line react/prefer-stateless-function
  constructor(props) {
    super(props);

    this.state = {
      dateValue: new Date(),
      activeDateWidget: false,
    };
  }

  changeDate(date) {
    this.setState({
      dateValue: date,
    });
  }

  changeActiveDateWidget(e) {
    e.stopPropagation();
    this.setState({
      activeDateWidget: !this.state.activeDateWidget,
    });
  }

  render() {
    const { input, meta } = this.props;
    const { dateValue, activeDateWidget } = this.state;
    return (
      <div>
        <input
          {...input}
          className="form-control"
          type="text"
          value={dateValue}
          onClick={this.changeActiveDateWidget}
          // onBlur={this.changeActiveDateWidget}
        />

        {activeDateWidget ? (
          <div>
            <DatePicker
              changeActiveDateWidget={this.changeActiveDateWidget}
              changeDate={this.changeDate}
              dateValue={dateValue}
            />
          </div>
        ) : (
          <div />
        )}
      </div>
    );
  }
}
export default DayInput;

import React from 'react';
import 'react-day-picker/lib/style.css';
import DayPicker, { DateUtils } from 'react-day-picker';

class DatePicker extends React.Component { // eslint-disable-line react/prefer-stateless-function
  constructor(props) {
    super(props);
    this.state = {
      selectedDay: new Date(),
    };
  }

  componentDidMount() {
    if (this.input) {
      this.input.focus();
    }
  }

  handleDayClick(e, day, { disabled }) {
    e.stopPropagation();
    if (disabled) {
      return;
    }
    this.setState({ selectedDay: day }, () => {
      this.props.changeDate(day);
      this.props.changeActiveDateWidget();
    });
  }

  focusThisComponent(e) {
    if (e) {
      this.input = e;
    }
  }

  render() {
    const { changeActiveDateWidget } = this.props;
    const { selectedDay } = this.state;
    return (
      <div
        ref={this.focusThisComponent}
        tabIndex="1"
      >
        <DayPicker
          id="THISTHING"
          initialMonth={selectedDay}
          selectedDays={day => DateUtils.isSameDay(selectedDay, day)}
          onDayClick={this.handleDayClick}
        />
      </div>
    );
  }
}

export default DatePicker;

如您所见,第一个组件包裹在第二个组件内。我尝试像这样自己转换第一个组件:

const DayInput = props => {
  <input
    {...props.input}
    type="text"
    value= {new Date()}
    onClick={()=>??}
   />
}

但正如您所见,我不知道如何处理 onclick 事件。有人可以帮我实现这一目标吗?

【问题讨论】:

  • 你会使用redux还是根组件的状态?
  • 您的 DayInput 没有返回任何内容
  • 根组件的状态。我从 DayInput 中返回,没有任何效果。只是我没有在这里包含它
  • @DanielLizik 是对的,您必须在组件中返回某些内容(将 {(..) 代表{ return (..) }
  • 有状态的组件工作正常,问题是我很难将它们转换为无状态

标签: javascript reactjs stateless stateful


【解决方案1】:

要将您的组件转变为无状态组件,您必须将所有内容作为组件的属性传递。

这会将您的 DayInput 拆分为 2 个组件:

const DayInputShow = props => {
  return (<input
    {...props.input}
    type="text"
    value= {props.value}
    onClick={(event)=>props.onClick()}
    />);
};

const DayInputEdit = props => {
  return (<DatePicker
    changeActiveDateWidget={props.changeActiveDateWidget}
    changeDate={props.onChange}
    dateValue={props.value}
  />);
};

DayInputShow.propTypes = {
  value: PropTypes.date,
  onClick: PropTypes.func,      
}

DayInputEdit.propTypes = {
  value: PropTypes.date,
  onChange: PropTypes.func,      
}

这将是根组件(不完整且仍是有状态的):

class DatePicker extends React.Component { // eslint-disable-line react/prefer-stateless-function
  constructor(props) {
    super(props);
    this.state = {
      selectedDay: new Date(),
    };
  }

  componentDidMount() {
    if (this.input) {
      this.input.focus();
    }
  }

  handleDayClick(e, day, { disabled }) {
    e.stopPropagation();
    if (disabled) {
      return;
    }
    this.setState({ selectedDay: day }, () => {
      this.props.changeDate(day);
      this.props.changeActiveDateWidget();
    });
  }

  focusThisComponent(e) {
    if (e) {
      this.input = e;
    }
  }

  render() {
    const { changeActiveDateWidget } = this.props;
    const { selectedDay } = this.state;
    let dayPicker;
    if (this.input) {
      dayPicker = <DayPickerEdit
          value={this.state.selectedDay}
          onChange={(value) => {this.setState({selectedDay: value})}}
          selectedDays={day => DateUtils.isSameDay(selectedDay, day)}
          onDayClick={this.handleDayClick}
        />
    } else {
      dayPicker = <DayPickerShow
          value={this.state.selectedDay}
          ref={(input) => { this.inputRef = input; }} />
          onClick={() => {this.focusThisComponent(this.inputRef )}}
        />
    }
    return (
      <div
        ref={this.focusThisComponent}
        tabIndex="1"
      >
        {dayPicker }
      </div>
    );
  }
}

export default DatePicker;

【讨论】:

  • 好伙伴...但我想知道...我们可以将根组件转换为无状态吗?
  • 是的,你可以,但你需要一个 redux 商店。您会将所有状态存储在您的商店中,但使用和阅读会非常方便。
  • 我必须这样做,因为我的项目必须不使用有状态组件
猜你喜欢
  • 2018-12-02
  • 2018-01-22
  • 2020-01-23
  • 1970-01-01
  • 2016-06-08
  • 2017-06-08
  • 2018-06-02
  • 2018-10-18
  • 2018-08-29
相关资源
最近更新 更多