ReactJS 组件不使用状态变量渲染文本区域

ReactJS component not rendering textarea with state variable

我在 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 正确呈现。

问题来自这部分:

<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 字符串在可变文本区域中正确打印。

注意我的浏览器显示:

Warning: Use the defaultValue or value props instead of setting children on <textarea>.

但我会稍后修复这个问题,因为我认为它对当前的问题没有影响。

编辑: 我考虑了你的评论(到目前为止),所以我更新了我的代码:

                <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>

这是输出:

第二次编辑:

我上传了一个样本 app 突出了这个问题。我希望这有助于找到合适的解决方案

实际上,这正是错误所在。来自 docs:

If you want to initialize the component with a non-empty value, you can supply a defaultValue prop.

从 React 文档中检查此 link:React Textarea Value

基本上,对于 textArea,React 不支持包含在其中的文本,您需要将其指定为 valuedefaultValue.

正确的方法是

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

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

valuedefaultValue的区别在于specifying defaultValue leaves the component uncontrolled:

With an uncontrolled component, you often want React to specify the initial value, but leave subsequent updates uncontrolled. To handle this case, you can specify a defaultValue attribute instead of value.

...而 specifying value instructs React to control the component,这意味着您需要更新值 属性 以确保更改反映在组件中:

Since the value attribute is set on our form element, the displayed value will always be this.state.value, making the React state the source of truth.

要清楚地了解值/默认值之间的差异,请检查以下内容:Fiddle for value Default Value Distinction 控制台将始终显示新值,但组件不会。

我遇到了同样的问题。我通过使用受控组件解决了它,例如

state.value = this.props.value 
<textarea value={this.state.value} onchange={handler} />

控制输入部分效果很好。但是,我还有另一个问题,只要有重新渲染,我就需要 init/change 将 state.value 更改为 props.value。

我使用了提升循环方法,效果非常好。

componentWillReceiveProps: function(){
    this.setState({
        value: this.props.value
    }) }

希望这对您有所帮助。