ReactJS组件不使用状态变量呈现textarea [英] ReactJS component not rendering textarea with state variable

查看:141
本文介绍了ReactJS组件不使用状态变量呈现textarea的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在React中遇到一个有趣的错误。



我有这个组件:

 'use strict'; 
从'../stores/SummaryStore'导入SummaryStore;
import来自'react'的React;

导出默认类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);
}
}
返回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 fadeid =summaryModal>
< form>
< div className =modal-dialog>
< div className =modal-content>
< div className =modal-header>
< button type = buttonclassName =closedata-dismiss =modalariaLabel =Close>< span ariaHidden =true>& times;< / span>< / button>
< div style = {{color:'black'}}>
{this.state.sStarClassName.map(function(pCurrentClassName){return(< span className = {pCurrentClassName}>< / span> ;
);
})}
< h4 className =m odal-title> {this.state.sCurrentBookToShow.title}摘要< / h4>
< / div>
< / div>
< div className =modal-body>

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

< / div>
< div className =modal-footer>
< button type =buttonclassName =btn btn-defaultdata-dismiss =modal>关闭< / button>
< input type =submitclassName =btn btn-primaryvalue =Save/>
< / div>
< / div>
< / div>
< / form>
< / div>
);
}
}

您可能会注意到,它是突出了这个问题。我希望这有助于找到合适的解决方案

解决方案

从反应文档中检查此链接: React Textarea Value



基本上for textArea react不支持包含在其中的文本,您需要指定为 value defaultValue



正确的方式是

 < textarea name =descriptionvalue =这是一个描述。 /> 

 < textarea name =descriptiondefaultValue =这是一个描述。 /> 

与<$ c的区别$ c> defaultValue 是指定 defaultValue 使组件不受控制


对于不受控制的组件,您通常希望React为指定初始值,但不保持后续更新。要处理这种情况,您可以指定defaultValue属性而不是value。


...而指定指示React控制组件,这意味着你需要更新value属性以确保更改反映在组件中:


由于在我们的表单元素上设置了value属性,因此显示值将始终为this.state.value,使React状态成为事实的来源。


要清楚地了解它们之间的区别值/默认值检查:小提取价值默认值区分控制台将始终显示新值但组件将没有。


I am facing an intriguing bug in React.

I have this component:

'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>
               );
    }
}

As you might notice, it's a controller-view listening at a store which is registered to my AppDispatcher.

The steps above are correctly performed. i.e, when the particular action is triggerd, my component is correctly rendered with the variables {this.state.sCurrentBookToShow.title} and this.state.sCurrentBookToShow.title up-to-date.

The problem comes from this part:

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

The string is not printed in the the textarea.

I tried this to debug:

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

the summary string printed correctly inside the mutable textearea.

Note that my browser says:

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

But I will fix this later since I think it doesn't have an effect on the current problem.

EDIT: I took your remarks (so far) in consideration, so I updated my code like so:

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

  • I replaced this.state.sCurrentBookToShow.title by .summary to make sure the ladder is not empty.
  • I put the summary into a defaultValue prop

Here is the output:

Second edit:

I uploaded a sample app that highlights the issue. I hope this would help to find a proper solution

解决方案

Check this link from react docs: React Textarea Value

Basically for textArea react does not supports text enclosed within and you rather need to specify that as value or defaultValue.

The right way thus is

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

or

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

The difference with value and defaultValue is that 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.

...while specifying value instructs React to control the component, meaning you need to update value property to make sure that change is reflected in 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.

To get a clear idea of difference between value / default value check this: Fiddle for value Default Value Distinction Console will always show new value but component will not.

这篇关于ReactJS组件不使用状态变量呈现textarea的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆