Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ReactJS component not rendering textarea with state variable

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 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: enter image description here

Second edit:

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

like image 552
Mayas Avatar asked Jun 09 '15 11:06

Mayas


1 Answers

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.

like image 56
Jyoti Puri Avatar answered Sep 17 '22 11:09

Jyoti Puri