Skip to content

regression: formsy's validations prop uses stale values from higher scope (props and state are frozen in the state in which it mounted) #731

@blurymind

Description

@blurymind

I observed this after upgrading from 1.1.4 to 2.3.2

Image

If you try to pass state or props to custom validations functions - they are no longer a reference to the live values but are instead static values of the initial mount.

I made a minimal example here to try
https://codesandbox.io/p/sandbox/2m4j5p

Image

In case you cant open codesandbox

import { useState, useEffect } from "react";
import Formsy, { withFormsy } from "formsy-react";

const Input = ({ errorMessage, value, type, setValue }) => {
  const onChange = (event) => {
    setValue(event.target.value);
  };

  return (
    <div>
      <input onChange={onChange} value={value} type={type} />
      <span>{errorMessage}</span>
    </div>
  );
};
const FormsyInput = withFormsy(Input);
export default function App() {
  const [timer, setTimer] = useState(0);
  const [canSubmit, setCanSubmit] = useState(false);
  const disableButton = () => {
    setCanSubmit(false);
  };

  const enableButton = () => {
    setCanSubmit(true);
  };

  const submit = (model) => {
    fetch("http://example.com/", {
      method: "post",
      body: JSON.stringify(model),
    });
  };

  useEffect(() => {
    setInterval(() => {
      // console.log("timer");
      setTimer((prev) => prev + 0.5);
    }, 1000);
  }, []);

  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>
      <Formsy
        onValidSubmit={submit}
        onValid={enableButton}
        onInvalid={disableButton}
      >
        <FormsyInput
          name="timer"
          validations={{
            isTimer: (values, value) => {
              // BUG - timer no longer updates <-------------------
              console.log({ value, timer });
              // Props or State from a higher scope are frozen in theit value during mount
              return value && value > parseInt(timer);
            },
          }}
          validationErrors={{ isTimer: "Value is lower than timer" }}
          required
          type="number"
        />
        <button type="submit" disabled={!canSubmit}>
          can submit if value is higher than timer
        </button>
      </Formsy>
      {timer}
    </div>
  );
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions