Crak_mboutin
Crak_mboutin

Reputation: 1086

React textarea with value is readonly but need to be updated

I have a textarea in my React app who is filled with a value. I want this textarea to be updated and the form submited to update the row in the database.

<textarea id="description" className="materialize-textarea" length="120" value={description} disabled={isDisabled}></textarea>

The description variable fill the textarea with the value from the database. The field is not disabled.

I tried to attach an onChange event who dispatch an action (redux) to change the value of the textarea, but it trigger for each letter and it's too slow.

How can i create a textarea who is filled by a value and is editable?

Thank you!

Upvotes: 3

Views: 16770

Answers (2)

David L. Walsh
David L. Walsh

Reputation: 24818

If you're finding using the onChange event too slow, you can simply read from the DOM in the submit handler using refs. An example is shown here:

https://facebook.github.io/react/docs/tutorial.html#adding-new-comments

Since you're using redux, you can probably export a lot of that functionality to an action creator.

Upvotes: 1

J. Mark Stevens
J. Mark Stevens

Reputation: 4945

Here is a component with two textareas. There is a controlled relation between props and state. That is the key for inputs. Note componentWillReceiveProps.

    import React, {Component} from 'react';

    import Actions from '../../flux/Actions';

    let CurrentSnipDivSty = {
        height: 'calc(((100% - 40px) * .4) - 3px)',
        minHeight: '9.5em',
        width: '100%'
    };

    let CurrentSnipTextAreaSty = {
        backgroundColor: '#213919',
        border: '1px solid #314929',
        color: '#afac87',
        fontSize: '1em',
        height: 'calc(50% - 20px)',
        overflowY: 'auto',
        padding: '5px',
        width: 'calc(100% - 12px)'
    };

    class SnipsDetailRender extends Component {
        render() {
            let snip = this.state.snip.snip;
            let comment = this.state.snip.comment;

            return (
                <div id='CurrentSnipDivSty' style={CurrentSnipDivSty}>
                    <textarea
                        value={snip}
                        onChange={this.handleSnipChange}
                        style={CurrentSnipTextAreaSty} />
                    <textarea
                        value={comment}
                        onChange={this.handleCommentChange}
                        style={CurrentSnipTextAreaSty} />
                </div>
            );
        }
    }

    export default class SnipsDetail extends SnipsDetailRender {
        constructor() {
          super();
            this.state = { snip: {snip: '', comment: ''} };
        }
        componentWillReceiveProps = (nextProps) => {
            if ((nextProps.data.snip != this.state.snip.snip) || (nextProps.data.comment != this.state.snip.comment))
             this.setState({snip: nextProps.data});
        }
        handleSnipChange = (ev) => {
            let newSnip = {snip: ev.target.value, comment: this.state.snip.comment};
            this.setState({snip: newSnip});
            Actions.saveSnipEdit(newSnip);
        }
        handleCommentChange = (ev) => {
            let newSnip = {snip: this.state.snip.snip, comment: ev.target.value};
            this.setState({snip: newSnip});
            Actions.saveSnipEdit(newSnip);
        }
    }

Upvotes: 3

Related Questions