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.

Helper methods for errors object

See original GitHub issue

Is your feature request related to a problem? Please describe. Many component libraries have a property on their fields which decide whether is is invalid or not. For example, in the case of material ui this is the “error” property. It’s a boolean, so you always need a != null there, as errors.fieldName is an object, not a boolean.

Also when writing the error message somewhere you’ll always have to check if the object at errors.fieldName exists before you access the message at errors.fieldName.message, or else you’ll get an exception if there’s no error.

This looks the following in material ui:

error={errors.fieldName != null} helperText={errors.fieldName && errors.fieldName.message}

Describe the solution you’d like I think this could be solved by adding two simple helpers. error.message(‘fieldName’) -> Returns either the error message or undefined, if there’s no error error.has(‘fieldName’) -> Returns true if there’s an error, or else false

Then you could go like the following:

error={errors..has('fieldName')} helperText={errors.message('fieldName')}

I think that’s more clean and simple.

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Reactions:1
  • Comments:26 (15 by maintainers)

github_iconTop GitHub Comments

3reactions
bopfercommented, Sep 19, 2019

I am using Material UI + TypeScript + react-hook-form and I do this:

error={!!errors.fieldName} helperText={<FieldError error={errors.fieldName} />}

The !! makes it a boolean, which is required in MUI’s types. Then the component for helperText gives me one place to handle the rendering for all form fields. In there I can check to see if there is a message to show. If there is no error message to show, then FieldError just returns an empty fragment: <></>.

2reactions
hbarceloscommented, Nov 22, 2019

@bluebill1049 I’d like to +1 this.

I would like to add such a helper but at the same time, it increases the bundle size of this lib […]

I don’t think 2 helper functions with 1 or 2 lines each add significant overhead in terms of bundle size.

I just discovered this library and so far I think it is awesome, however, I do not think it is reasonable to ask users to include something like lodash for very simple functionality that is basically the core of the lib.

I’ve implemented helpers like this:

const hasError = inputName => Boolean(errors && errors[inputName]);
const getError = inputName => (hasError(inputName) ? errors[inputName].message : '');

Problem is that such functions are not pure, since they close over the errors object which is returned from useForm. So I end up with one of the following scenarios:

1. Declare such helper functions inside every component I have

Problem: it is very repetitive and boring having to copy and paste it for every form I have. Some applications might have dozens of different forms.

2. Make the functions pure

And use currying to ease the use:

const hasError = errors => inputName => Boolean(errors && errors[inputName]);
const getError = errors => inputName => (hasError(inputName) ? errors[inputName].message : '');

Then in my component I would have:

const { register, handleSubmit, errors } = useForm();
const formHasError = hasError(errors);
const formGetError = getError(errors);

Problem: This would also be very repetitive if spread throughout many forms in a given application.

3. Using lodash

I would have to do something like:

<TextField
    error={_.has(errors, 'email')}
    helperText={_.get(errors, 'email.message', '')}

Problem: if I don’t use lodash anywhere else in the project, it is yet another dependency that I’ll have to add. I’m not even talking about the bundle size impact of adding lodash, because we have tree-shaking. I’m simply advocating against adding another dependency itself.


⚠️ Main problem ⚠️

With any of the above approaches, I would be creating a coupling between my app and this lib’s internals. I’m assuming that errors is a plain object with a message property inside an email one.

This might hold true for now, but maybe in the future you can come up with another internal structure for this library, which would break my application. It would be very painful to change all my forms to comply to the new structure.

Ideally, you should probably not export the raw errors object at all. What I think would be useful for most users would be something like the following interfaces:

type ValidationPredicate = (value: string | boolean | number) => boolean;

type ValidationType = |
  | 'required'
  | 'maxLength'
  | 'minLength'
  | 'max'
  | 'min'
  | 'pattern'
  | ValidationPredicate
  | Record<string, ValidationPredicate>;

interface ValidationError {
  type: ValidationType;
  types: Record<string, string | boolean>;
  message: string;
  ref: React.RefObject;
}

interface Validation {
  hasErrors(): boolean;
  hasError(name: string): boolean;
  getErrorMessage(name: string): string;
}

If you really need to expose the errors object (maybe to not break retro-compatibility), then there could have something like:

type ErrorsObject = Record<string, ValidationError> & Validation;
const errors: ErrorsObject = { /* ... */ };

Usage would be like:

const { validation, register, handeSubmit } = useForm();
// ...
<TextField
    error={validation.hasError('email')}
    helperText={validation.getErrorMessage('email')}

Since the code that returns the Validation object closes over the raw errors object, you could easily export the detached versions of those methods. Then usage could be more like:

const { hasError, getErrorMessage, register, handeSubmit } = useForm();
// ...
<TextField
    error={hasError('email')}
    helperText={getErrorMessage('email')}
Read more comments on GitHub >

github_iconTop Results From Across the Web

laravel - Create helpers function for displaying validation errors
This can be easily solved by passing the $errors object to the isError() helper method. Helper. function isError($errors, $name){ if ...
Read more >
Module: ActionView::Helpers::ActiveRecordHelper - Rails API
Returns a string with a DIV containing all of the error messages for the objects located as instance variables by the names given....
Read more >
Wildcard Capture and Helper Methods (The Java™ Tutorials ...
In this example, the compiler processes the i input parameter as being of type Object. When the foo method invokes List.set(int, E), the...
Read more >
Best Practices for exceptions - .NET - Microsoft Learn
Learn best practices for exceptions, such as using try/catch/finally, handling common conditions without exceptions, and using predefined .
Read more >
Configuration Helper Object - Ivanti
The methods listed below provide error reporting as a HRESULT which can be tested for in VBScript using the Err object. Success is...
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