0

I am stuck trying to figure out how to update my button in real time. I have read through quite a few forums/threads (React form onChange->setState one step behind) on how to fix the issue but haven't been able to apply it to my solution to get the button to dynamically update on the correct action, it is 1 behind.

  constructor(props: EditRole | Readonly<EditRole>) {
    super(props);
    this.state = {
      originalName: '',
      name: '',
      sealId: '',
      rolesSearchPrefix: '',
      permittedRoles: '',
      sealIdError: '',
      oldSealId: '',
      oldRolesSearchPrefix: '',
      oldPermittedRoles: '',
      valueUpdated: false
    };
    this.saveRole = this.saveRole.bind(this);
    this.handleChangeRoles = this.handleChangeRoles.bind(this);
  }

  componentDidMount() {
    this.getRole();
  }

  getRole() {
    store.getRole(this.props.match.params.name).then((res: any) => {
      const { name, sealId, rolesSearchPrefix, permittedRoles } = res.data;
      this.setState({ originalName: name, sealId, oldSealId: sealId, rolesSearchPrefix, oldRolesSearchPrefix: rolesSearchPrefix, permittedRoles, oldPermittedRoles: permittedRoles });
    });
  }
    
  handleChangeRoles = (e: Event) => {
    this.setState({ ...this.state, permittedRoles: (e.target as HTMLInputElement).value }, () => {
      (e.target as HTMLInputElement).value === this.state.oldPermittedRoles ? this.setState({ ...this.state, valueUpdated: false }) : this.setState({ ...this.state, valueUpdated: true });
    });
  }

As you can see in the code above, I am getting my role and I set the values in the state. This is all working. Then when I get to my form:

<form>
  <input
    id="roles"
    label="Roles"
    value={this.state.permittedRoles}
    // onChange={this.handChangeRoles}
    // onChange={(e) => this.setState({ ...this.state, permittedRoles: (e.target as HTMLInputElement).value, valueUpdated: true })}
    onChange={(e) => this.handleChangeRoles(e)}
    multiline={true}>
  </MdsTextInput>
  {backButton} {this.state.valueUpdated ? nextButton : disabledButton}
</form>

The update is happening correctly, characters are updating the value however the button status is not changing until I click off the form. So if I'm in the input field, value is "test" the button is disabled. I type "a" ("testa") and noting changes until I click out of the input field, which it then appropriately enables the button. I want it to dynamically update. I have tried a few different things (you can see a few commented out onChanges) and tried a few different ways with layering the setState (tried to set the disable/enable first before the value, tried using 2 buttons (current above) to show/hide instead of setting the "disable" property to T/F). None of the solutions so far updated immediately, I've had to wait until I click out, giving me the appropriate results. Does anyone know what my issue is?

I appreciate your time.

Speakmore
  • 3
  • 1

1 Answers1

0

you don't need to set the state after setting the value. since you don't update your oldPermittedRoles and you have your permittedRoles value on your onChange event you also don't need to updated state value because you are going to update it together. One setstate is enough, you can achieve it like this:

handleRoles = (e: React.ChangeEvent<HTMLInputElement>) => {
    const { target } = e;
    this.setState((prevState) => ({
        ...prevState,
        permittedRoles: target.value,
        valueUpdated: prevState.oldPermittedRoles !== target.value ? true : false
    }))
}

When you update permitted roles it will also update button state

Ozan Mudul
  • 750
  • 1
  • 9
  • 20
  • Thanks for the response. I've tried a variation of this, as well as even having the button's state just update (first), and they're all still a step behind. I type into the input field "x" then have to click out for the button to disable/enable. The state is correct, but my UI is not updating instantly until the next action -- which I've been unable to solve. – Speakmore Feb 18 '22 at 14:00
  • EDIT: Turns out it might be the component library I'm using... A regular input field updates the state right away. My library is slowing it down, requiring a click off..? – Speakmore Feb 18 '22 at 14:07
  • I don't know what you are using but you need to divide your task into subtasks – Ozan Mudul Feb 18 '22 at 23:40