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
Creating and editing note experience should be the same #310
Conversation
src/components/ui/Note.js
Outdated
@@ -187,22 +190,32 @@ class Note extends PureComponent<Props, State> { | |||
} | |||
|
|||
handleEditorValueChange = (onValueChange: Function) => (value: any) => { |
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 given how we changed the component, the value
argument should be renamed to event
and set its type to SyntheticEvent<HTMLTextAreaElement>
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.
Correct that the way which I followed on auto
PR. Thanks 👍
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.
@reyronald I applied changes but. After I added this Event definition for this method I ended up with multiple errors so I was forced to use in the event type definition
(value: any)
to resolve them. I there is a possibility to solve this easily please let me know how to deal with that.
I guess the value can be anything right now from SyntheticEvent to any other object. You can try for example with mixed and it will crush for several places. I would really appreciate your help. Cheers
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.
That's because in the body of that function you are using .target
instead of .currentTarget
which is a common mistake, it's described in the Flow documentation here: https://flow.org/en/docs/react/events/
Note: To get the element instance, like
HTMLButtonElement
in the example above, it is a common mistake to useevent.target
instead of event.currentTarget. The reason why you want to use
event.currentTarget` is that event.target may be the wrong element due to event propagation.
If you go directly to the Flow definition of SyntheticEvent
in react-dom
and check the target
property, you'll even find more context:
declare class SyntheticEvent<+T: EventTarget = EventTarget, +E: Event = Event> {
bubbles: boolean;
cancelable: boolean;
+currentTarget: T;
defaultPrevented: boolean;
eventPhase: number;
isDefaultPrevented(): boolean;
isPropagationStopped(): boolean;
isTrusted: boolean;
nativeEvent: E;
preventDefault(): void;
stopPropagation(): void;
// This should not be `T`. Use `currentTarget` instead. See:
// https://github.com/DefinitelyTyped/DefinitelyTyped/issues/11508#issuecomment-256045682
+target: EventTarget;
timeStamp: number;
type: string;
persist(): void;
}
A more thorough explanation of why we should use currentTarget
instead is explained in that link: DefinitelyTyped/DefinitelyTyped#11508 (comment)
So, Flow's libdefs were designed to prevent this common mistake :). That's why it's always helpful to annotate things properly because then the tool will prevent us from doing unintended things.
With that fix it'll clear the errors you were getting related to that. After, you'll have to update the type of the onChange
prop over at InputField
too, but if you do it properly you'll get errors from other places of the app that are doing the same mistake, so I would suggest just using any
there:
onChange?: (value: any) => void,
It was untyped anyway before so you wouldn't be doing any more harm!
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 haven't tested it with those changes, but if applying them break the functionality you were aiming for just roll them back and disregard the suggestion, not worth it to spend more time debugging it just to fix that tiny thing 😅
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.
Thanks a lot for the detailed answer I really appreciate it! I think I had the same thoughts while I was adding those changes. So the question is?
I added the definition for the onChange function like this:
onChange?: (value: any) => mixed,
And you introduce the void return (actually is this the specification of return type for functions?)
onChange?: (value: any) => void,
Should I change it to void? It was previously declared as mixed. WDYT? @reyronald
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.
According to official docs, () => mixed
should be used for types that accept arbitrary functions. For our case when we have a defined function signature and it doesn't return anything, use of void
should be fine. That's how I understand it though 😄
So, for this specific case, I'd suggest changing to void
as it's more explicit type signature cc @galileo
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.
Just like Nick said, I guess () => mixed
was chosen here so that it would accept arbitrary functions.
But in this case, event listeners are not really arbitrary functions, they all have the same base shape where they accept an Event as an argument and return nothing, so that's why in my snippet I changed it to onChange?: (value: any) => void
. You can see how it's defined here:
https://developer.mozilla.org/en-US/docs/Web/API/EventListener/handleEvent (check "Return value")
And also the official specs (a little bit harder to interpret but you'll notice it doesn't return anything there either):
25c1196
to
097e828
Compare
a3d517c
to
80a9a8e
Compare
80a9a8e
to
cad4b42
Compare
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.
Hey @galileo This looks very good now. I tested this in a browser locally and can confirm it behaves consistently, we no longer show a medium-formatting toolbar when selecting anything, we still preserve line breaks and highlight links. Good work!
Please just check several things related to the code. And check my input in this thread: #310 (comment)
src/components/ui/Note.js
Outdated
@@ -186,23 +190,35 @@ class Note extends PureComponent<Props, State> { | |||
return TextWrapper({}, <Text content={content} isPureContent />) | |||
} | |||
|
|||
handleEditorValueChange = (onValueChange: Function) => (value: any) => { | |||
this.setState({ newValueIsValid: !!value.trim() }) | |||
handleEditorValueChange = (onValueChange: Function) => (event: SyntheticEvent<HTMLTextAreaElement>) => { |
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.
Since Function
is unsafe and should be avoided(link), I'd use exactly () => mixed
type for the onValueChange
callback. Would like to see what you guys think.
cc @galileo @reyronald
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.
But this is our general approach or from now because we are using a lot of Function
definition, you can check in this file. For me it is misleading for this project if I can not base my assumption on the current project state 🤔
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.
Not everything we have in a project is correct apparently and we should fix it whenever possible. Once we're on this use case, let' fix it here.
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.
Thanks for answering. Just to confirm. We, want to support for now both notations in the code?
/> | ||
) | ||
} | ||
|
||
handleCancel = () => { | ||
const { text = '' } = this.props | ||
|
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.
Not a change request, just some thoughts on code structure. For short methods that are 3-4 lines long, it's fine to have no empty lines. It's just when the method body is longer it's good to group logical blocks of code and separate them with empty lines.
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.
Over time we should eliminate all the use cases of unsafe types like Function
, any
, and Object
. Since we can't do that at once, we're better focusing on fixing things in the area that we touch :)
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.
LGTM the way it is now @galileo, thanks for applying the changes!
cad4b42
to
ca1f3bc
Compare
Changes applied |
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.
Latest changes look great to me :) Thanks Kamil! Happy to merge that now.
* Change inline editor for notes * Add review requested changes * Change types defintions * Add build # Conflicts: # lib/auto-ui.js # lib/auto-ui.js.map
Release Type: Non-Breaking Feature
Fixes https://x-team-internal.atlassian.net/browse/XP-2518
Description
We decided to follow recently with the path where we will align Notes experience which will only show us the plain textarea editor.
Checklist
Before submitting a pull request, please make sure the following is done:
In Review
orIn Progress
depending on its status)IN REVIEW
columnnpm run lint
)npm run flow
)npm run jest
).stories.js
file) is changed or added accordingly to reflect any new or updated use cases or variants usage.Steps to Test or Reproduce
Impacted Areas in Application
Notes Inline editing, NotesFeed
Screenshots