React form onChange->setState one step behind

前端 未结 7 1519
南方客
南方客 2020-12-02 12:21

I encountered this problem building a webapp and I replicated it in this jsfiddle. Essentially, I would like an input to call this.setState({message: input_val})

相关标签:
7条回答
  • 2020-12-02 12:38

    There is a much simpler way to do this, setState(updater, callback) is an async function and it takes the callback as second argument,

    Simply pass the handleSubmit as a callback to setState method, this way after setState is complete only handleSubmit will get executed.

    For eg.

    handleChange: function(e) {
        console.log(e.target.value);
        this.setState({message: e.target.value}, this.handleSubmit);
    }
    

    Try to change the handleChange() method like above and it will work.

    for syntax of using setState check this link

    0 讨论(0)
  • 2020-12-02 12:41

    There's no reason for MyForm to be using state here. Also putting the onChange on the form instead of the input you're interested in is odd. Controlled components should be preferred because their behavior is more obvious, and any time App's message state changes (even if you e.g. allow Message to change it later), it'll be correct everywhere.

    This also makes your code a bit shorter, and considerably simpler.

    var App = React.createClass({
        getInitialState: function() {
            return {message: ''}
        },
        appHandleSubmit: function(message) {
            this.setState({message: message});
        },
        render: function() {
            return (
                <div className='myApp'>
                    <MyForm onChange={this.appHandleSubmit} 
                            message={this.state.message} />
                    <Message message={this.state.message}/>
                </div>
            );
        }
    });
    
    var MyForm = React.createClass({
        handleInputChange: function(e){
            this.props.onChange(e.target.value);
        },
        // now always in sync with the parent's state
        render: function() {
            return (
                <form className="reactForm">
                    <input type='text' onChange={this.handleInputChange}
                           value={this.props.message} />
                </form>
            );
        }
    });
    

    jsbin

    0 讨论(0)
  • 2020-12-02 12:41

    I found it very cumbersome for me to define 3 handler functions just to get some value to a component's state, so I decided not to use state at all. I just defined an additional property to the component that stored desired value.

    So I ended up with a code that looked something like this:

    //...
    },
    text: '',
    handleChange: function(event) {
      this.text = event.target.value;
      this.forceUpdate();
    },
    render: function() {
        return <div>
          <InputComponent onChange={this.handleChange}/>
          <DisplayComponent textToDisplay={this.text}/>
          </div>
    }
    //...
    
    0 讨论(0)
  • 2020-12-02 12:43

    A call to setState isn't synchronous. It creates a "pending state transition." (See here for more details). You should explicitly pass the new input value as part of the event being raised (like to handleSubmit in your example).

    See this example.

    handleSubmit: function(txt) {
        this.props.onChange(txt);
    },
    handleChange: function(e) {
        var value = e.target.value;
        this.setState({message: value});
        this.handleSubmit(value);
    },
    
    0 讨论(0)
  • 2020-12-02 12:49

    I was pulling my hair out for like an hour because of this so I decided to share... If your callback is still one step behind and seemingly not working, ensure you don't CALL the function with parenthesis... Just pass it in. Rookie mistake.

    RIGHT:

    handleChange: function(e) {
        console.log(e.target.value);
        this.setState({message: e.target.value}, this.handleSubmit);
    }
    

    VS

    WRONG:

    handleChange: function(e) {
        console.log(e.target.value);
        this.setState({message: e.target.value}, this.handleSubmit());
    }
    
    0 讨论(0)
  • 2020-12-02 12:53

    with setState hook

    useEffect(() => {
        your code...
    }, [yourState]);
    
    0 讨论(0)
提交回复
热议问题