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

Make Select components clearable by default #478

Merged
merged 6 commits into from
May 5, 2021

Conversation

TyMick
Copy link
Collaborator

@TyMick TyMick commented May 3, 2021

FLCOM-6739

It was noted as confusing that clearing a Select component leaves an old value in the input. After investigating the React Select docs, I'm guessing that such components weren't clearable at all, since its Select components have an isClearable prop that is falsy by default.

This PR adds an explicit isClearable prop to all Styled UI Select components and gives it a default value of true.

Probably the easiest way to test this would be to check out the branch, then yarn && yarn build && yarn catalog-start, then go to http://localhost:4000/#/text-input/select go to https://deploy-preview-478--faithlife-styled-ui.netlify.app/#/text-input/select.

TyMick added 4 commits May 3, 2021 09:02
This Hook reverted a breaking change introduced in React Select v3
while Styled UI was still in v5. There's a TODO note on it to remove the
Hook in v6, and we're already warning about this breaking change in the
v6 upgrade guide, so I think it best to remove it now. This isn't
essential to this PR, though.

If this commit is merged, I'll post a special notice in the Styled UI
flow.
@RobertBolender
Copy link
Contributor

Probably the easiest way to test this

FYI, we have a PR build environment 😄
You can find the link under "Show all checks"
https://deploy-preview-478--faithlife-styled-ui.netlify.app/

@TyMick
Copy link
Collaborator Author

TyMick commented May 3, 2021

Oh that's much better! 😅

Four components was getting to be a lot to keep prop transformation
logic in sync between, especially as I'm about to add a Hook to all of
them that uses seven more props.
@TyMick
Copy link
Collaborator Author

TyMick commented May 4, 2021

I've added functionality to clear the Select value when the user is typing (for clearable, single-value Selects). Probably ventured into "too clever" territory by the end of it, but I was never stuck, and it always felt like I was nearly there... But at least this was just one day of work this time. I'll use this to continue training my forecasting skills—ideally I should've pushed back about this extra functionality being necessary in a spring-cleaning sprint. And stopped at some point to take the time to figure out how to explain what my plan was.

@TyMick
Copy link
Collaborator Author

TyMick commented May 4, 2021

This is ready for another look, by the way, @RobertBolender 👍🏼

Copy link
Contributor

@RobertBolender RobertBolender left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not totally convinced that we want to support the optionally-controlled-state pattern/hook long-term, but I'm a big fan of the useCommonSelectProps cleanup and am very happy with the UX improvement with clearing the Single Select when typing.

Let's be sure to merge this with Rebase, not Squash, to preserve the individual commits.

[innerOnSelectChange, isClearable, isMulti, onInputChange, setInputValue],
);

return [selectValue, innerOnSelectChange, inputValue, innerOnInputChange];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit (non-blocking): I realize this hook is pretty tightly coupled to the selects so it's not a huge deal although can we return an object here? My general rule of thumb is to prefer returning objects from hooks when

  1. There are more than two values being returned
  2. The hook is likely to be called once and only once in a component

My reasoning for this is so that A) consumers are encouraged to use consistent variable names and B) consumers don't have to worry about getting the order correct when destructuring

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good call! 👌🏼

const [value, setValue] = useState(
controlledValue !== undefined ? controlledValue : defaultValue,
);
useEffect(() => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit (non-blocking): I think this hook could be simplified a bit

const isControlled = controlledValue !== undefined;

const [value, setValue] = useState(isControlled ? controlledValue : defaultValue);

if (isControlled) {
    return [controlledValue, EMPTY_FUNCTION];
}

return [value, setValue];

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This way saves you a useEffect call and a few lines of code

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice utility hook by the way!

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh yeah, I suppose that useEffect is a bit useless there. 😅 Thanks! I think I'll simplify it a bit more to

const [value, setValue] = useState(defaultValue);

if (controlledValue !== undefined) {
  return [controlledValue, EMPTY_FUNCTION];
} else {
  return [value, setValue];
}

then, since value and setValue won't be used if controlledValue's defined.

@TyMick
Copy link
Collaborator Author

TyMick commented May 4, 2021

As we'll be rebasing instead of squashing for this one, I'll edit the last commit instead of adding another so the git history's more useful.

Comment on lines +48 to +56
return {
innerValue: selectValue,
innerOnChange: innerOnSelectChange,
innerInputValue: inputValue,
innerOnInputChange,
};
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@josephdangerstewart and @RobertBolender, the new return object for useClearableSelectValue. Involves some name changes that make more sense outside the Hook.

Comment on lines +15 to +21
const [value, setValue] = useState(defaultValue);

if (controlledValue !== undefined) {
return [controlledValue, EMPTY_FUNCTION];
} else {
return [value, setValue];
}
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@josephdangerstewart, the simplified useOptionallyControlledState body.

Only for clearable single-value Selects.
@TyMick TyMick merged commit dec996b into Faithlife:master May 5, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

3 participants