-
Notifications
You must be signed in to change notification settings - Fork 16
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
feat: ui.text_area #652
feat: ui.text_area #652
Conversation
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.
Include some examples that you tested with. Looking good
const [value, setValue] = useState(propValue ?? defaultValue); | ||
const [pending, setPending] = useState(false); | ||
const prevPropValue = usePrevious(propValue); | ||
|
||
// Update local value to new propValue if the server sent a new propValue and no user changes have been queued | ||
if ( | ||
propValue !== prevPropValue && | ||
propValue !== value && | ||
propValue !== undefined && | ||
!pending | ||
) { | ||
setValue(propValue); | ||
} | ||
|
||
const propDebouncedOnChange = useCallback( | ||
async (newValue: string) => { | ||
try { | ||
await propOnChange(newValue); | ||
} catch (e) { | ||
log.warn('Error returned from onChange', e); | ||
} | ||
setPending(false); | ||
}, | ||
[propOnChange] | ||
); | ||
|
||
const debouncedOnChange = useDebouncedCallback( | ||
propDebouncedOnChange, | ||
VALUE_CHANGE_DEBOUNCE | ||
); | ||
|
||
const onChange = useCallback( | ||
(newValue: string) => { | ||
setPending(true); | ||
debouncedOnChange(newValue); | ||
setValue(newValue); | ||
}, | ||
[debouncedOnChange] | ||
); |
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.
We should be able to extract this into a hook and share it with TextField
. Something like const [value, onChange] = useDebouncedValue<T = string>(propValue, defaultValue, propOnChange)
VALUE_CHANGE_DEBOUNCE | ||
); | ||
|
||
const onChange = useCallback( |
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.
Side note about onChange
- we should only have it set to a defined value if the passed in propOnChange
is defined. In some cases, simply passing in a function will change the behaviour of the component, so we don't want to always pass in a function if the propOnChange
function was not provided.
So in this case it'd be something like:
const onChangeCallback = useCallback( ... );
const onChange = propOnChange ? onChangeCallback : undefined;
See useFormEventCallback.ts
as another example (and it's usage in Form.tsx).
|
||
|
||
def text_area( | ||
icon: Element | None = None, |
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.
For convenience, we can probably allow an icon string here as well, and automatically convert it to a ui.icon
element if it's provided.
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.
Do we want to do this though, seems inconsistent since we don't do it tab.py
, text_field.py
, list_action_group.py
with summary_icon
?
|
||
const VALUE_CHANGE_DEBOUNCE = 250; | ||
|
||
function useDebouncedOnChange<T = string>( |
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.
This hook should probably be implemented in @deephaven/react-hooks. Doesn't seem to have anything plugins specific unless I'm missing someting.
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.
@AkshatJawne Does this add any functionality that useDebouncedCallback
doesn't already provide?
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.
nvm, I see what it is doing.
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.
I can look into implementing on the DHC side, thought it would be more appropriate here, since Bender had referenced the useFormEventCallback.ts
, and that lives in the plugins repo.
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.
Where is useFormEventCallback
referenced?
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.
I think that's just an example of a hook that properly handles the undefined callback scenario and not necessarily tying it to plugins repo.
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.
Wouldn't be opposed to it, if @mofojed has no issues with it, I can do it -- just holds up the process a little more, have to create a separate web-client-ui PR, wait for that to merge, and then wait for the version bump and then this will be able to be merged, right?
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.
No need to move it to @deephaven/react-hooks
- we can keep it in mind but there's no pressing need to, we don't need to wait for a bump/publish cycle to use it here, just add it here.
|
||
function useDebouncedOnChange<T = string>( | ||
propValue: T | undefined, | ||
defaultValue: T, |
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.
I don't think the defaultValue
prop makes sense inside of this hook. I would just support value
and onChange
inputs and coalesce the value ?? defaultValue
in the calling component.
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.
Good shout, yeah I think this makes sense, will make change.
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 is a chance you can use useDebouncedValue
and don't need a new hook at all.
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.
Gonna try rn
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.
nvm, I don't think that allows the debouncing in the change handler passed into the component
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.
Although, just on first sight, I will need onChange for the textField, which the useDebouncedValue
doesn't give access to
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.
Yeah, disregard the useDebouncedValue
idea :)
const icon = | ||
typeof propIcon === 'string' ? ( | ||
<Icon> | ||
<FontAwesomeIcon icon={getIcon(`deephaven.ui.icons.${propIcon}`)} /> | ||
</Icon> | ||
) : ( | ||
propIcon | ||
); |
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.
I would prefer this on the Python side. Just change icon=icon
on text_area.py#187 to icon=ui.icon(icon) if type(icon) == 'str' else icon
and it should be good.
It's better practice to do it Python side when possible as we may have default props set in the Python code.
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.
Closes #649
Additional Info:
validate
prop based off this comment on Text Field PR: docs: text field #357 (comment)Some of the snippets I had tested with: