4

I'm working on a form in my ReactJs app. What I'd like to do:

1/ select a draft letter from an array of draft letters by its id // ok

2/ display the title, body and location of the selected draft letter in a form below // ok

3/ then the user should be able to edit all the fields // not ok!

This is what I did :

class NewLetter extends Component {

    constructor(props) {
        super(props)
        this.state = {
            city: "",
            title: "",
            letterBody: "",
        }
        this.handleChange_city = this.handleChange_city.bind(this);
        this.handleChange_letterBody = this.handleChange_letterBody.bind(this);
        this.handleChange_title = this.handleChange_title.bind(this);
    }

    handleChange_city(e) {
        this.setState({
            city: e.target.value
        });
    }

    handleChange_letterBody(e) {
        this.setState({
            title: e.target.value
        });
    }


    handleChange_title(e) {
        this.setState({
            letterBody: e.target.value
        });
    }


    render() {
        return (

            <form className="containerLetter">

                <div className="form-group">
                    <input type="text" className="form-control" id="letterLocation" placeholder="where are you?" value={this.props.city} onChange={this.handleChange_city}/>

                </div>

                <div className="form-group">
                    <input type="text" className="form-control" id="letterTitle" placeholder="give a title to your letter" value={this.props.title} onChange={this.handleChange_title} />
                </div>

                <div className="form-group">
                    <textarea type="text" className="form-control" id="letterBody" placeholder="Letter content" value={this.props.letterBody} onChange={this.handleChange_letterBody} />
                </div>

                <button className="actionButton">Send the letter</button> <br />
                <button className="actionButton">Save as draft</button>

            </form>


        )
    }
}

export default NewLetter

If I use value, the fields are not editable If I use defaultValue the field are editable but when the defaultValue change, React doesn't re-render. The values are passed as props by the parent component:

class DraftLetters extends Component {

    constructor(props) {
        super(props)
        this.state = {
            selectedDraftIndex: 0,
        };
        this.handleChange = this.handleChange.bind(this);
    }


    getListOfDrafts = () => {
        var list = []
        for (let i = 0; i < this.props.drafts.length; i++) {
            list.push(<option value={i}> {this.props.drafts[i].redactionDate} </option>);
        }
        return (list);
    }


    handleChange(e) {
        this.setState({
            selectedDraftIndex: e.target.value,
        })
    }


    render() {
        return (
            <div >

                {(this.props.drafts.length != 0) &&
                    <div className="form-group selectLetter">
                        <label for="sel1">Select the draft:</label>
                        <select onChange={this.handleChange} className="form-control" id="sel1">
                            {this.getListOfDrafts()}
                        </select>
                    </div>
                }

                {(this.props.drafts.length == 0) &&
                    <div className="form-group">
                        <p className="noLetter"> You haven't saved any draft.</p>
                        <img width="400px" className="img-fluid" src={painting} alt="tableau"></img>
                    </div>
                }

                <div>
                    <br />
                    {(this.props.drafts.length != 0) &&
                        <NewLetter city={this.props.drafts[this.state.selectedDraftIndex].city}
                            title={this.props.drafts[this.state.selectedDraftIndex].title}
                            letterBody={this.props.drafts[this.state.selectedDraftIndex].letterBody}></NewLetter>
                    }

                    {this.state.selectedDraftIndex}
                </div>
            </div>
        )
    }
}


export default DraftLetters

It seems to be a well known problem

This is what I found: defaultValue change does not re-render input

React input defaultValue doesn't update with state

https://github.com/facebook/react/issues/4101

Is there nowdays a fix for this problem?

Julien Berthoud
  • 721
  • 8
  • 24
  • Can you show `handleChange_city` or `handleChange_title` or `handleChange_letterBody` – Andus Jan 10 '20 at 18:00
  • Sure, see my edit. My idea was to use the handleChange method to update the state of my letter element, and then I will implement the persistence of the final state in the DB. – Julien Berthoud Jan 10 '20 at 19:16
  • I don't understand which part is not working, I have test the code and I am able to edit the three input fields.. – Andus Jan 10 '20 at 19:29
  • I add some code so that you can see where my props are coming from. The problem is that my form fields are not editable. – Julien Berthoud Jan 10 '20 at 19:46
  • 1
    I've just found this https://kentcdodds.com/blog/understanding-reacts-key-prop that describes my problem and a workarround – Julien Berthoud Jan 10 '20 at 20:03

0 Answers0