2016-07-21 12 views
1

レンダリング時に計算されるプロパティに基づいてコンポーネントの状態を設定する必要があるところが数回ありました。その結果、コンポーネントが時折再レンダリングされます。これは大きな懸念ではありませんが、ハッキーではなく「反応の道」ではないと感じています。だから私は誰かがより良い解決策を持っているかどうか疑問に思います。参考文献の影響を受けるリアクションウェイの状態

したがって、最新の例は、展開可能なテキストコンポーネントです。

enter image description here

airbnb

のレビュー要素と同様にこれはかなり簡単でした。しかし、最後の部分は、オーバーフローがあるかどうかを検出し、不要な場合は[詳細]オプションを表示しないことでした。私が思いついた解決策は、scrollHeightがclientHeightよりも大きいかどうかをチェックし、それに基づいていくつかの状態を設定することでした。これは私のソリューションの簡略版です。

import React, { Component, PropTypes } from 'react'; 
 
import classNames from 'classnames' 
 

 
function isOverflowed(element) { 
 
    return element.scrollHeight > element.clientHeight; 
 
} 
 

 
export default class ExpandableText extends Component { 
 
    static propTypes = { 
 
    content: PropTypes.string, 
 
    maxHeight: PropTypes.number, 
 
    }; 
 

 
    static defaultProps = { 
 
    isOpen: false, 
 
    maxHeight: 10, 
 
    } 
 

 
    constructor(props) { 
 
    super(props); 
 

 
    this.handleOpen = this.handleOpen.bind(this); 
 
    this.handleClose = this.handleClose.bind(this); 
 

 
    this.state = { 
 
     isOpen: props.isOpen, 
 
     isOverFlowed: true, 
 
    }; 
 
    } 
 

 
    componentDidMount() { 
 
    if (!isOverflowed(this.refs.content)) { 
 
     this.setState({ isOpen: true, isOverFlowed: false }); 
 
    } 
 
    } 
 

 
    handleOpen() { 
 
    this.setState({ isOpen: true }); 
 
    } 
 

 
    handleClose() { 
 
    this.setState({ isOpen: false }); 
 
    } 
 

 
    render() { 
 
    const { content, maxHeight } = this.props; 
 
    const { isOpen, isOverFlowed } = this.state; 
 
    const contentClassName = classNames('expandable-text', { 
 
     'expandable-text__content--closed': !isOpen, 
 
     'expandable-text__content--open': isOpen, 
 
    }); 
 
    const actionsClassName = classNames('expandable-text__actions', { hide: !isOverFlowed }) 
 
    return (
 
     <div className="expandable-text"> 
 
     <div 
 
      ref="content" 
 
      className={contentClassName} 
 
      style={{ 
 
      maxHeight: isOpen ? 'none' : `${maxHeight}rem`, 
 
      }} 
 
     > 
 
\t \t \t <p>{content}</p> 
 
     </div> 
 
     <div className={actionsClassName}> 
 
      <button onClick={isOpen ? this.handleClose : this.handleOpen}>{isOpen ? 'Close': 'Open'}</button> 
 
     </div> 
 
     </div> 
 
    ); 
 
    } 
 
}

そうそこに起こってまともな量があるが、重要なことは、私はオーバーフローをチェックして、それに基づいて状態を(潜在的に)設定していますcomponentDidMountです。

これはおそらく、高さではなく文字数の制限や他の解決策を適用することで実現できると私は認識しています。しかし、ソリューションがこれに似ていると仮定すると、これを行うためのより反応的な方法がありますか? (これは再レンダリングを必要としません)

答えて

0

これは問題ありません!オーバーフローするかどうかを検出する前に、テキストをレンダリングする必要があります。

文字や行の数をカウントするような何かの面倒なことがあります。しかし、フォントサイズはクライアントごとに大きく異なる可能性があるので、オーバーフローサイズの "良い"推測に終わるだけです。

もう1つのことは、何らかの理由で/ユーザーがそれを見ることができないところで、テキストを「キャンバスから外して」、ターゲットコンテナと同じように動作するコンテナにレンダリングすることです。オーバーフローを測定し、実際のコンテナへのレンダリングを開始します。オーバーフローすることはありません。

+1

寝ると、これは思ったほど悪い考えではありません。プレーンなJSを使用する場合は、オーバーフローを検出するために同じことを行い、クラスをボタンセクションに追加して非表示にします。ここでは、私はすべてのことを再レンダリングしているように感じますが、vDom diffgo algoは本質的に同じものになるはずです(単に 'hide'クラスが追加されます)。私が変更できる唯一の事は、デフォルトでそれを隠すことです。もしあなたが存在してはいけないボタンのフラッシュを取得していない場合は、遅れがあります。私はこれをここに残して、他の誰かが貢献しているかどうかをもう少し見てみよう – aray12