web-dev-qa-db-ja.com

ReactJSコンポーネントが状態変数でtextareaをレンダリングしない

Reactの興味深いバグに直面しています。

私はこのコンポーネントを持っています:

'use strict';
import SummaryStore from '../stores/SummaryStore';
import React from 'react';

export default class ChangeSummaryForm extends React.Component {
   constructor() {
       // store initialisation
       SummaryStore.register();

       var vRating = SummaryStore.getBookForSummaryPrint().summaryRating;
       var vStarClassName = this.getRatingClasses(vRating);
       this.state = {
            sStarClassName: vStarClassName,
            sCurrentBookToShow: SummaryStore.getBookForSummaryPrint()
       };

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

  getRatingClasses(pRating) {
      var vI, vStarClassName = [];
       for(vI = 0; vI < 4; vI++) {
          if(pRating > 0) {
             vStarClassName.Push("glyphicon glyphicon-star");
             pRating--;
          } else {
             vStarClassName.Push("glyphicon glyphicon-star-empty");
          }
       }
      return vStarClassName;
  }
  componentDidMount() {
    SummaryStore.addChangeListener(this.thereIsASummaryToShow);
  }

  componentWillUnmount() {
    SummaryStore.removeChangeListener(this.thereIsASummaryToShow);
  }

  thereIsASummaryToShow() {

      this.setState({sCurrentBookToShow: SummaryStore.getBookForSummaryPrint(),
                     sStarClassName: this.getRatingClasses(SummaryStore.getBookForSummaryPrint().rating)
                    });
      $("#summaryModal").modal('show');
    }
    render() {
        return (<div className="modal fade" id="summaryModal">
                  <form>
                    <div className="modal-dialog">
                    <div className="modal-content">
                      <div className="modal-header">
                        <button type="button" className="close" data-dismiss="modal" ariaLabel="Close"><span ariaHidden="true">&times;                  </span>                           </button>
                <div style={{color: 'black'}}>
                    {this.state.sStarClassName.map(function(pCurrentClassName) { return (<span className={pCurrentClassName}></span>
                                                                                   );
                                                                                 })}
                        <h4 className="modal-title">Summary of {this.state.sCurrentBookToShow.title}</h4>
                </div>
                      </div>
                      <div className="modal-body">

                            <div className="form-group">
                                <textarea className="form-control" rows="22" ref="summaryContent" >{this.state.sCurrentBookToShow.summary}</textarea>
                            </div>

                      </div>
                      <div className="modal-footer">
                        <button type="button" className="btn btn-default" data-dismiss="modal" >Close</button>
                        <input type="submit" className="btn btn-primary" value="Save"/>
                      </div>
                    </div>
                  </div>
                    </form>
                </div>
               );
    }
}

お気づきかもしれませんが、これは controller-view AppDispatcherに登録されているストアでリッスンしています。

上記の手順は正しく実行されます。つまり、特定のアクションがトリガーされると、コンポーネントは変数{this.state.sCurrentBookToShow.title}およびthis.state.sCurrentBookToShow.title up-to-dateで正しくレンダリングされます。

問題はこの部分から来ています:

<textarea className="form-control" rows="22" ref="summaryContent" >   
  {this.state.sCurrentBookToShow.summary}
 </textarea>

文字列はテキストエリアに印刷されません。

私はこれをデバッグしようとしました:

    render() {
     var summary = "this is a summary";
     return (// .. shortened for brevity
      <textarea className="form-control" rows="22" ref="summaryContent">
       {summary}
    </textarea> ..);
    }

可変テキスト領域内にsummary文字列が正しく印刷されました。

私のブラウザは言うことに注意してください:

警告:<textarea>に子を設定する代わりに、defaultValueまたはvalue小道具を使用してください。

しかし、現在の問題に影響はないと思うので、後で修正します。

EDIT:私はあなたの発言を(これまでのところ)考慮に入れたので、コードを次のように更新しました:

                <h4 className="modal-title">Summary of {this.state.sCurrentBookToShow.summary}</h4>
        </div>
              </div>
              <div className="modal-body">

                    <div className="form-group">
                        {this.state.sCurrentBookToShow.summary}
                        <textarea className="form-control" rows="22" ref="summaryContent" defaultValue={this.state.sCurrentBookToShow.summary}></textarea>
                    </div>
  • ラダーが空でないことを確認するために、this.state.sCurrentBookToShow.title.summaryに置き換えました。
  • 要約をdefaultValueプロップに入れました

出力は次のとおりです。 enter image description here

2番目の編集:

サンプルをアップロードしました app この問題を強調しています。これが適切な解決策を見つけるのに役立つことを願っています

22
Mayas

反応ドキュメントからこのリンクを確認してください: React Textarea Value

TextAreaの基本的な反応は、囲まれたテキストをサポートしていないため、valueまたはdefaultValueとして指定する必要があります。

したがって、正しい方法は

<textarea name="description" value="This is a description." />

または

<textarea name="description" defaultValue="This is a description." />

valuedefaultValueとの違いは、 defaultValueを指定するとコンポーネントが制御されないままになる

制御されていないコンポーネントでは、多くの場合、Reactで初期値を指定しますが、後続の更新は制御されません。この場合、値の代わりにdefaultValue属性を指定できます。

... while valueを指定するReactコンポーネントを制御する 、つまり、valueプロパティを更新して、変更が確実に反映されるようにする必要があります成分:

Value属性はフォーム要素に設定されているため、表示される値は常にthis.state.valueになり、React stateが真実の源となります。

値/デフォルト値の違いを明確に把握するには、次を確認してください。 値のデフォルト値の区別のフィドル コンソールは常に新しい値を表示しますが、コンポーネントは表示しません。

39
Jyoti Puri

実際、それがまさに問題です。 docs から:

コンポーネントを空でない値で初期化する場合は、defaultValueプロパティを指定できます。

0
gcedo