Search code examples
javascriptreactjsbuttoninputonchange

how come e.target.value is only capturing the first letter in string input in reactjs


The input is only capturing the first letter in the string input. And is that method is correct?

class Example extends React.Component{

    state={
        name:'Ajith'
    }

    changeEvent = (e) => {
        console.log('change : '+this.state.name)
        let name = this.state.name;
        this.setState({
            name : e.target.value
        });
    }

    edit = () => {
        console.log('edit : '+this.state.name)
        this.setState({
            name : <input value={this.state.name} ref = {(input) =>{this.Edit = input}} onChange={this.changeEvent}/> 
        });
    }

    render()
    {
        console.log('render : '+this.state.name)
        return(
            <div>
                <button onClick={this.edit}>
                    Edit
                </button>
                {this.state.name}
            </div>
        )
    }
}

ReactDOM.render(
    <Example />,
    document.getElementById("root")
);
<div id="root"></div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>


Solution

  • You're converting from the input back to the string on the change event, which is fired for every change to the field in React (not just when the user leaves the field). If you wait until the user's done (for instance, using blur), it works. (Or an OK button, or...) Also strongly recommend storing just the name, not switching between the name and an input for it; just use a flag and conditional rendering. Also note that you don't need a ref for this at all.

    Some reading: Forms in the documentation

    More reading: Arrow Functions in Class Properties Might Not Be As Great As We Think

    class Example extends React.Component{
    
        state = {
            name: 'Ajith',
            editing: false
        };
    
        changeEvent = (e) => {
            this.setState({
                name: e.target.value
            });
        };
        
        blurEvent = (e) => {
            this.setState({editing: false});
        };
    
        edit = () => {
            this.setState({editing: true});
        };
    
        render() {
            return(
                <div>
                    <button onClick={this.edit}>
                        Edit
                    </button>
                    {this.state.editing
                    ? <input type="text" value={this.state.name} onChange={this.changeEvent} onBlur={this.blurEvent} />
                    : this.state.name
                    }
                </div>
            );
        }
    }
    
    ReactDOM.render(
        <Example />,
        document.getElementById("root")
    );
    <div id="root"></div>
    
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>