0

I am building a simple react app where a user enters a number and it is displayed on the screen.

class Main extends React.Component {
    state = {
        list: [1,2,3,4,5]
    }
    newElementHandler = (e) => {
        let newlist = this.state.list
        newlist.push(e.target.value)
        this.setState({
            list: newlist
        })
    }
    submitHandler = (e) => {
        e.preventDefault()
    }
    render() {
        let showlist = this.state.list
        return (
            <div>
                <div>
                {showlist.map(ele=>(
                    <div>{ele}</div>
                ))}
                </div>
                <form onSubmit={this.submitHandler}>
                    <input onChange={this.newElementHandler} />
                    <button type="submit" >Submit</button>
                </form>
                
            </div>
        )
    }
}

ReactDOM.render(<Main />, document.querySelector('.react'));
<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>
<div class='react'></div>

However, I only want the number to be displayed when clicked "Submit". Right now, it displays the number as soon as i start typing. Can someone please help modify this code so that it only updates the state on form submission and hence displays the number. Thanks

2 Answers 2

1

Remove the change handler, since you want to render changes only when the form is submitted. Use a ref to get a reference to the input element inside the submit handler, retrieve the value, and call setState:

class Main extends React.Component {
    state = {
        list: [1, 2, 3, 4, 5]
    }
    inputRef = React.createRef();
    submitHandler = (e) => {
        e.preventDefault()
        this.setState({
          list: [
            ...this.state.list,
            this.inputRef.current.value
          ]
        });
    }
    render() {
        let showlist = this.state.list
        return (
            <div>
                <div>
                    {showlist.map(ele => (
                        <div>{ele}</div>
                    ))}
                </div>
                <form onSubmit={this.submitHandler}>
                    <input ref={this.inputRef} />
                    <button type="submit" >Submit</button>
                </form>

            </div>
        )
    }
}

ReactDOM.render(<Main />, document.querySelector('.react'));
<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>
<div class='react'></div>

Note that since you're using React, you should not mutate the state - clone / spread state instead when updating, like I did above. (Avoid .push)

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks a lot ... :)
since you mentioned about not mutating state directly, I have another doubt. Suppose the state was a single variable (say num: 1) instead of an array, Can i write: let new_num = this.state.num in my code...or is there any other method?
Yes, primitives like numbers are fine to use/change directly. It's only non-primitives (arrays and objects, mostly) that you need to make sure not to mutate. (Primitives are immutable)
1

Before my answer, please take a note that the following:

    let newlist = this.state.list
    newlist.push(e.target.value)

Is a no-no! You should never mutate your state directly, but need to only modify a copy of it:

    const newlist = [...this.state.list];
    newlist.push(e.target.value);

Or:

const newlist = [...this.state.list, e.target.value];

For the answer itself, you have either options:

a. Use another state slice that holds the current value:

import React, { Component } from 'react';
import { render } from 'react-dom';
import Employee from './Employee';
import {EmployeeProvider} from './context';
import './style.css';

class Main extends Component {
    state = {
        list: [1,2,3,4,5],
        currentValue: '',
    }
    newElementHandler = (e) => {
      this.setState({
        currentValue: e.target.value
      })
    }
    submitHandler = (e) => {
        e.preventDefault();
        this.setState({
          list: [...this.state.list, this.state.currentValue],
          currentValue: ''
        });
    }
    
    render() {
        let showlist = this.state.list
        return (
            <div>
                <div>
                {showlist.map(ele=>(
                    <div>{ele}</div>
                ))}
                </div>
                <form onSubmit={this.submitHandler}>
                    <input value={this.state.currentValue} onChange={this.newElementHandler} />
                    <button type="submit" >Submit</button>
                </form>
                
            </div>
        )
    }
}
render(<Main />, document.getElementById('root'));

b. Use Form data:

import React, { Component } from 'react';
import { render } from 'react-dom';
import Employee from './Employee';
import {EmployeeProvider} from './context';
import './style.css';

class Main extends Component {

    state = {
        list: [1,2,3,4,5],
    }
    submitHandler = (e) => {
        e.preventDefault();
        const formData = new FormData(e.target);
        this.setState({
          list: [...this.state.list, formData.get('value')]
        })
    }
    
    render() {
        let showlist = this.state.list
        return (
            <div>
                <div>
                {showlist.map(ele=>(
                    <div>{ele}</div>
                ))}
                </div>
                <form onSubmit={this.submitHandler}>
                    <input name='value' />
                    <button type="submit" >Submit</button>
                </form>
                
            </div>
        )
    }
}
render(<Main />, document.getElementById('root'));

c. Use refs (@CertainPerformance's answer)

2 Comments

Thanks...also since you mentioned about not changing state directly, I have another doubt. Suppose the state was a single variable (say num: 1) instead of an array, Can i write: let new_num = this.state.num in my code...or is there any other method?
You can write it, and if num is primitive, than you can mutate new_num and then use it to update the state or so, but doing something like this.state.num++ is wrong since it mutates the state object.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.