-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
bug: Calculate component error handling fix #3805
Conversation
Removed vultr server and associated DNS entries |
revert: change to sampleResult refactor: simpler conditional logic fix: remove console logs
values.defaults, | ||
); | ||
|
||
if (Number.isNaN(Number(result))) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As mentioned in the description, I have used this to catch issues with the NumberInput
component which existed but wasn't picked up because we were never blocking the update of the comp
}); | ||
|
||
const sampleResult = React.useMemo(() => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tried to ensure this was an additive fix, I didn't want to take away too much which makes the component work because I couldn't fully grasp how it all functioned within the timeboxed time
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So what I think is happening here is that the useMemo()
and associated array are just covering the same functionality as validateOnChange: true
.
The pattern we want to follow, and other components employ, is to keep validateOnChange: false
and then handle validation onSubmit.
I think this means removing this custom validation function, and just using formik 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It also feeds the "Try" field which gives you a preview of the formula output:
<p>
<strong>{formik.values.output || "<output>"}</strong> would be set
to <strong>{sampleResult}</strong>.
</p>
I could maybe move it to state and use that in the validation step as well, updating with a useEffect or something but, this felt like a change on top of the bug fix.
Happy to do a bit more on this if you think it is worth it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Aha, thanks. This is what I've missed 👍
So we do need a way to get a runtime result out which is sampleResult
.
I think I'd aim to see if there's a way we can avoid duplicating the validation logic - maybe a function with a signature like this could work in both instances?
type Validate = (values: Calculate) => [result: number | undefined, errors: FormikErrors<Calculate>]
This would look something like this -
validate: (values) => {
const [_, errors]: validate(values);
return errors;
},
...
const sampleResult = React.useMemo(() => {
const [result, _]: validate(formik.values);
if (!result) return UNKNOWN
}, [formik.values, validate]);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@DafyddLlyr got to the end of my timebox and didn't get it working as required. It's definitely possible though and I'll make a note for a potential follow-up PR to tidy this up, if that sounds good to you?
I was mostly caught resolving types and harmonising return messaging.
formik.values.defaults, | ||
); | ||
// Type guard as mathjs evaluates `m` to a "Unit" object for "meter" | ||
if (!Number.isNaN(Number(result))) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is !Number.isNaN(Number(result))
actually the same as original type guard check typeof result === "number"
? What's motivation for rewriting this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From what I could work out, the result would return a string
if you were using a data field populated by a NumberInput
so result === "number"
would return false
, although the calculation would work fine. This wasn't a problem when validating on change in the way it was, because it didn't stop you adding the calculate component, but it was a problem when I used Formik to validate on submit, which blocked it.
if (!Number.isNaN(Number(result))) { | ||
return result; | ||
} else { | ||
return `the ${typeof result}: '${result}'`; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added this to ensure clear error messaging is given to Editors
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now got it showing nothing if undefined, which feels right. I kept getting weird behaviour on existing Calculate components when using formik.dirty
so I've not used it for conditional rendering
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tricky one! I think it's worth spending a bit more time here aiming to leave both the bug fixed and the code better than we found it.
Happy to jump on a call post-dev call and talk it through if helpful 👍
if (!Number.isNaN(Number(result))) { | ||
return result; | ||
} else { | ||
return `the ${typeof result}: '${result}'`; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bug report here: https://trello.com/c/kmRRM7uQ/3041-remove-incorrect-calculate-component-errors-for-valid-formulas
To fix this, I changed how errors were handled in the component, using Formik for the error handling and moving it to validate onsubmit rather than on change.
Main change is here:
I have changed the condition from
typeof result === "number"
toNumber.isNaN(Number(result))
so we can properly deal withString
values coming from theNumberInput
componentRefactor Opportunity
There's a slight repetition of logic here between
validate:{}
andSampleResult
which we could look to refactor in future. The refactor could either look to put SampleResult within aUseEffect()
and use it within theuseFormik({validate:{}})
or add a new function to deal with the validation separately which would output{result, errors}
as noted by @DafyddLlyr below.Although logic is similar, the return messaging is different between the two with the
validate:
logic focusing on error messaging whereas theSampleResult()
focuses on use guidance and help.