question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Form onValidation shouldn't throw

See original GitHub issue

Enhancement

Current form onValidation property has two design issues: 1. It throws. 2. It throws non-error.

First, validation method shouldn’t throw it should return a report/explanation why data is invalid. Programmer should decide what to do with this report and probably throw exception. Validation should throw only when something went wrong like invalid options were passed.

Second, throwing non-error object leads is an error-prone behavior due to lack of stack it could lead to hard to track bugs. It seems ok while you control the code within you component, but it still a very bad design.

Motivation

Avoiding this allow to create some unified method, which could be used anywhere outside of the component without a single change.

Possible implementations

It’s better when validation method returns an array of issues, and have the next interface:

type Validator = (any, object?): Array<Issue>

type Issue = {
  path: Array<string|number>
  rule: string
  details: object
}

Simple number validator:

function validateNumber(value:any):Array<Issue> {
  if (typeof value === 'number') {
    return []
  }
  else {
    return [
       {rule: 'isNumber', path: [], details: {expect: true, is: false}}
    ]
  }
}

Such issues could be used with i18n package. Its’ creation could be wordy, but it solvable with factory methods.

You can check how this implemented on practice at TypedProps package.

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Reactions:2
  • Comments:22 (15 by maintainers)

github_iconTop GitHub Comments

2reactions
rumkincommented, Nov 8, 2019

@diegohaz I mean that validator itself shouldn’t throw its result. The result of validation method call should be returned. And the error should be thrown only when something unexpected happen. But, when you try to send (or use somehow) the data that hasn’t pass the validation, then you should throw.

Throwing non-errors considered as anti-pattern/bad practice anyway. Here are references in eslint and bluebird documentations:

1reaction
diegohazcommented, Jun 3, 2020

I see your point here, but my point was more about versioning. With separate package you can introduce a breaking change into forms (experimetal and opinionated) part and bump major only for this exact package without affecting base package which is tend to be much more stable.

Oh yeah! Right now it’s being “solved” by prefixing the module with unstable_. And I think it’s a matter of how many subjetive decisions we want to make.

With this naming approach, we can say that every new module should start as unstable/experimental, so there’s no hard decision to make here.

But we do have one subjective decision to make: when will this module become stable? For Composite, which will be stable in v1.1.0, this means that it’s being used in production in a large project (WordPress) and all major issues and API decisions were already made and tested.

If we start having modules as separate packages, the subjective decisions we would have to make would increase: should this new module be in a separate package? Will it eventually be integrated into the base library? etc.

And the same question remains: when will this module become stable?

I don’t discard this option (there’s even a @reakit npm scope available if we want to separate the library into more packages in the future). But right now I think separate packages should be used:

  1. When the component is built on top of other dependencies that don’t make sense being in the base library. For example, reakit-playground depends on buble, codemirror and emotion.

  2. When the component API is too different or doesn’t follow what’s described in our basic concepts, with components always rendering only one element and with state hooks exposed as a separate function.

    That would be the case, for example, if we come up with a high level component like <Calendar /> that abstracts all the internal components instead of exposing them separately.

I don’t think that’s the case, at least with the current Form API, which still follows the library’s basic concepts. If we want to experiment with completely different APIs, though, I agree that a separate package would be better.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Is it a good or bad idea throwing Exceptions when validating ...
It depends - if you are expecting the data to be there and NOT having the data is unexpected, then throwing ...
Read more >
Validation - Throw Exception or Return False? - Jenkov.com
When validating input data you do not always have to throw an exception if the input is invalid. How to handle invalid data...
Read more >
Why is it bad to use exceptions for handling this type of ...
On principle, do not throw data validation exceptions. Throwing only after performing all validations is not an exceptional case. Nor does it " ......
Read more >
A Definitive Guide to Sensible Form Validations
“The best form validation practice? “Avoid the need for throwing any error. Be preventive.” The field would be validated using a regular expression...
Read more >
[Form Validation] should not throw exception on remove field ...
This issue has been automatically marked as stale because it has not had recent activity. It will be closed in 30 days if...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found