【问题标题】:Derived state from props on React "truncate text" component从 React “截断文本”组件上的 props 派生的状态
【发布时间】:2019-03-22 09:17:34
【问题描述】:

我对 React 还很陌生,大约一周前才开始使用它。我正在尝试在组件中开发截断文本功能,但陷入了似乎是常见的新手陷阱。

我有一个病人信息组件,它显示了人们的个人数据,例如姓名、出生日期等。该组件在视觉上设计为固定宽度的卡片,当人名的宽度超过卡片:

Original text Truncated text

(“截断”格式非常具体,我不能仅使用 CSS)

我通过 props 将人的姓名和姓氏从父组件传递到子 PatientName 组件,该组件封装并处理截断功能。这是我正在使用的代码:

import './patient-name.css';

import React from 'react';
import PropTypes from 'prop-types';

const TRUNCATED_MAX_SURNAME_CHARS = 10;
const TRUNCATED_SURNAME_ELLIPSIS = '...';

const TRUNCATED_MAX_NAME_CHARS = 1;
const TRUNCATED_NAME_ELLIPSIS = '.';

class PatientName extends React.Component {
  constructor(props) {
    super(props);

    this.state = { name: props.name, surname: props.surname };

    this.$element = React.createRef();
    this.$name = React.createRef();
  }

  isOverflowing() {
    const elementRightPos = this.$element.current.getBoundingClientRect().right;
    const nameRightPos = this.$name.current.getBoundingClientRect().right;

    return nameRightPos > elementRightPos;
  }

  componentDidMount() {
    if (this.isOverflowing()) this.truncate();
  }

  truncate() {
    this.setState({
      name: `${this.props.name.substring(
        0,
        TRUNCATED_MAX_NAME_CHARS,
      )}${TRUNCATED_NAME_ELLIPSIS}`,
      surname: `${this.props.surname.substring(
        0,
        TRUNCATED_MAX_SURNAME_CHARS,
      )}${TRUNCATED_SURNAME_ELLIPSIS}`,
    });
  }

  render() {
    return (
      <h4 className="patient-name" ref={this.$element}>
        <span className="patient-surname">{this.state.surname}</span>
        &nbsp;
        <span ref={this.$name}>{this.state.name}</span>
      </h4>
    );
  }
}

PatientName.propTypes = {
  name: PropTypes.string,
  surname: PropTypes.string,
};

export default PatientName;

这工作正常(我现在不担心截断性能)...直到我在父组件中选择另一个患者。然后病人名字没有变,还是显示之前我通过props传过来的名字。

我知道问题是从道具派生状态,并且构造函数只被调用一次,并且状态之后永远不会刷新等等,但是......这样做的正确“反应方式”是什么?

我来自 Angular 背景,我仍在努力解决这个问题。

谢谢!

PS:我使用的是 React 16.6

【问题讨论】:

    标签: reactjs


    【解决方案1】:

    如果道具发生变化,您需要更新您的状态:

    componenDidUpdate(prevProps, prevState) {
      if (prevProps.name !== this.props.name || prevProps.surname !== this.props.surname) {
        this.setState({name: this.props.name, surname: this.props.surname});
      }
      else if (prevState.name !== this.state.name || prevState.surname !== this.state.surname) {
        if (this.isOverflowing()) this.truncate();
      }
    }
    

    首先if 更新状态并使用新的未截断props 重新渲染并获得新的测量值。第二个if 用于检查新的测量值并在需要时截断。

    【讨论】:

      【解决方案2】:

      从 React 16.3+ 开始,有一个新的组件生命周期,它是一个名为 getDerivedStateFromProps 的静态方法,它返回状态并在组件接收道具时触发

      所以在你的例子中,你可以这样使用它:

      static getDerivedStateFromProps(nextProps, state) {
         return ({
        ...state,
        name: `${nextProps.name.substring(
          0,
          TRUNCATED_MAX_NAME_CHARS,
        )}${TRUNCATED_NAME_ELLIPSIS}`,
        surname: `${nextProps.surname.substring(
          0,
          TRUNCATED_MAX_SURNAME_CHARS,
        )}${TRUNCATED_SURNAME_ELLIPSIS}`,
      });
      }

      【讨论】:

        猜你喜欢
        • 2023-03-08
        • 1970-01-01
        • 2017-01-02
        • 2018-11-23
        • 2020-02-26
        • 2018-11-14
        • 1970-01-01
        • 2020-09-30
        • 2020-11-06
        相关资源
        最近更新 更多