Skip to content
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

unusual event handling in TextInput "_onClearInput" breaks fully controlled components and requires unsustainable workarounds #1412

Open
elliot-wilson opened this issue Oct 22, 2024 · 0 comments
Labels
bug Something isn't working UI-Platform Owned by Platform Team

Comments

@elliot-wilson
Copy link
Contributor

elliot-wilson commented Oct 22, 2024

Component/Module

TextInput

Screenshots (if applicable)

Screen.Recording.2024-10-22.at.1.07.05.PM.mov

Reproduction Steps

import { TextInput } from "@narmi/design_system";
import { useState } from "react";

export function SearchBar() {
  const [searchTerm, setSearchTerm] = useState("");

  return (
    <TextInput
      value={searchTerm}
      label="Search"
      startIcon="search"
      onChange={(e: React.ChangeEvent<HTMLInputElement>) => setSearchTerm(e.target.value)}
      showClearButton
    />
  );
}

Expected Result

Clicking the "x" clear button sets the value to "".

Actual Result

Clicking the "x" clear button sets the value to undefined.

Additional Details / Context

Introduced by #953

If you use the showClearButton prop, the TextInput will call your onChange if you click the "x" IconButton:

function _onChange(e) {
if (onChange) {
onChange(e);
}
setInputValue(e.target.value);
}
function _onClearInput(e) {
_onChange(e);
setInputValue("");
}

This is problematic, because an onChange handler should be expecting an HTML change event, whereas an onClick action will trigger an HTML click event. For the click event, event.target.value will be undefined. That is, _onClearInput is passing the wrong kind of event to _onChange; it only looks like it's working because, in some cases, having an event target value of undefined is pretty close to an event target value of `"``. But not always!

There are two patterns that people seem to be using to avoid this:

  1. Using an un-controlled component.

https://github.com/narmi/banking/blob/e65066c412f6ffecff011bac153ae8ed55b69ed1/staff/src/components/ach_manager/AchManagerFilters.tsx#L21-L35

This might be fine in simple cases, but we can't assume that every TextInput will be uncontrolled.

  1. Guarding against an undefined target value, even though common sense says it should be truthy:

https://github.com/narmi/banking/blob/e24423e28ffd4876aa795af4077ff15aa120ccef/staff/src/pages/marketing/CampaignList.tsx#L98-L108

This code is not sustainable, because it just looks unnecessary from a TypeScript perspective. A ChangeEvent<HTMLInputElmenet> should never have an undefined target value. Someone will eventually "fix" it during a code cleanup.

Also, from a code maintenance perspective, we should not expect developers to write onChange callbacks that can handle either a change event or a click event. Doing so is unconventional in a way that will assuredly trip up future engineers.

Proposed solution

I'm not sure what the best approach is! Somehow synthesizing an onChange event with a target value "" feels wrong. It's probably better to require a clearInput prop where the consumer can supply a callback that -- 99%+ percent of the time -- will explicitly clear the value "".

@elliot-wilson elliot-wilson added bug Something isn't working UI-Platform Owned by Platform Team labels Oct 22, 2024
@elliot-wilson elliot-wilson changed the title unusual event handling in TextInput "_onClearInput" breaks fully controlled components and requires odd workarounds unusual event handling in TextInput "_onClearInput" breaks fully controlled components and requires unsustainable workarounds Oct 22, 2024
@edakrong edakrong added the IM-Weekly label Jan 10, 2025 — with Linear
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working UI-Platform Owned by Platform Team
Projects
None yet
Development

No branches or pull requests

2 participants