Search code examples
reactjsreact-final-form

Disable submit button until the answer from the server is received in react-final-form


Is it possible to disable submit button with <button disabled={submitting}> in react-final-form until the answer from the server is received? It takes about 6 seconds for the server to respond. But the button is being disabled for less than a second. Here is my submit function:

const sleep = ms => new Promise(resolve => setTimeout(resolve, ms))

const onSubmit = async values => {
  await sleep(100)
  let xhr = new XMLHttpRequest();
  xhr.open("POST", "https:...", true) ;
  xhr.setRequestHeader("Content-Type", "application/json");
  let data = {...}
  xhr.send(JSON.stringify(data));
  xhr.onreadystatechange = function() {
    if (xhr.readyState === 4) {
      if (xhr.status === 200) {
        let result = JSON.parse(xhr.responseText);
        if (result.status === "OK") {
          window.location = result.pdf
        };
      }
    }
  };
}

Is it possible to set submitting to true until I get result.status === "OK"?


Solution

  • You can do it however you need to move submitting to state. See example below

    import React from 'react'
    import { render } from 'react-dom'
    import { createForm } from 'final-form'
    
    const sleep = ms => new Promise(resolve => setTimeout(resolve, ms))
    
    const onSubmit = async values => {
      await sleep(300)
      window.alert(JSON.stringify(values, 0, 2))
    }
    
    class Form extends React.Component {
      constructor() {
        super()
        const initialState = {}
        let inConstructor = true
        this.form = createForm({ onSubmit })
    
        // subscribe to form changes
        this.unsubscribe = this.form.subscribe(
          formState => {
            // cannot call setState in constructor, but need to on subsequent notifications
            if (inConstructor) {
              initialState.formState = formState
            } else {
              this.setState({ formState })
            }
          },
          { submitting: true}
        )
        this.state = initialState
        inConstructor = false
      }
    
      componentWillUnmount() {
        this.unsubscribe()
        this.unsubscribeFields.forEach(unsubscribe => unsubscribe())
      }
    
      handleSubmit = event => {
        event.preventDefault()
        this.form.submit()
      }
    
      render() {
        const { formState} = this.state
        return (
            <form onSubmit={this.handleSubmit}>
              <div className="buttons">
                <button type="submit" disabled={formState.submitting}>
                  Submit
                </button>
              </div>
              <pre>{JSON.stringify(this.state, 0, 2)}</pre>
            </form>
        )
      }
    }
    
    render(<Form />, document.getElementById('root'))