-
Notifications
You must be signed in to change notification settings - Fork 2.7k
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
Adding componentRef support, BaseComponent warnings, and initial Customizer component. #1389
Conversation
…omizer implementation, adding warning helpers.
|
||
return (results && results.length > 1) ? results[1] : ''; | ||
return this.__className; |
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.
memoizing the classname as an optimization.
* never changes. | ||
*/ | ||
protected _onRenderNull(): JSX.Element | null { | ||
return null; |
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 as an fyi; I use this quite a bit in my other Button PR where i would like to return a function that renders nothing, but don't want to recreate it over and over (to avoid immutability issues)
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.
Should we move this to a const
outside of a class?
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.
These new warns are awesome. I want to make sure to communicate this to all developers. Considering a weekly React update to gather all of these new changes in a newsletter type form.
@@ -153,7 +235,7 @@ function _makeSafe(obj: BaseComponent<any, any>, prototype: Object, methodName: | |||
if (prototypeMethod) { | |||
retVal = prototypeMethod.apply(this, arguments); | |||
} | |||
if (classMethod) { | |||
if (classMethod !== prototypeMethod) { |
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 is an important bug fix; Previously, it would call the prototypeMethod twice if the subclass doesn't implement it.
import { BaseComponent } from './BaseComponent'; | ||
import { assign } from './object'; | ||
|
||
export interface ISettings { |
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'd like to check this in as an initial implementation, but will add examples and refine this in a separate PR.
Note that this isn't being exported yet until we use it.
@@ -44,6 +61,16 @@ export class BaseComponent<P, S> extends React.Component<P, S> { | |||
]); | |||
} | |||
|
|||
/** When the component will receive props, make sure the componentRef is updated. */ | |||
public componentWillReceiveProps(newProps?: any, newContext?: 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.
P
?
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.
Or IBaseProps<P>
?
* never changes. | ||
*/ | ||
protected _onRenderNull(): JSX.Element | null { | ||
return null; |
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.
Should we move this to a const
outside of a class?
packages/utilities/src/warn.ts
Outdated
@@ -0,0 +1,63 @@ | |||
let _warningCallback = _warn; | |||
|
|||
export interface IStringMap { |
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.
Can we improve typing here? Something like this:
type ISettingsMap<T> = {
[P in keyof T]?: string;
};
function foo<T>(object: T, deprecations: ISettingsMap<T>) {
for (let x in deprecations) {
alert(deprecations[x]);
}
}
////////
interface IX {
foo: number;
bar: string;
};
var x: IX = {
foo: 42,
bar: "test"
};
foo<IX>(x, {
"foo": "abc"
});
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.
thx for the comments, will try
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 news! I did this, and it caught some bugs where I misplaced some warnings! Yay typings!
…tly works, even if the component doesn't have a public interface. Adding placeholder public interfaces, which exposes a number of inconsistencies across the components ( all of the focusable components should have focus methods, for example)
*/ | ||
componentRef?: (component: ICheckbox) => void; | ||
|
||
/** |
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.
As discussed offline, I think it would be good if we could move this to an interface
interface IComponentRef<TComponent> {
componentRef?: (component: TComponent) => void;
}
and then add it to the component's props by extending multiple interfaces? Or by &
it in BaseComponent
? Shouldn't be a blocker for this change, but going forward it would be nice to centralize these shared props to make refactoring etc. easier.
(Left it as a comment on an outdated, commit, repeating here for visibility) As discussed offline, I think it would be good if we could move this ( interface IComponentRef<TComponent> {
componentRef?: (component: TComponent) => void;
} and then add it to the component's props by extending multiple interfaces? Or by |
…oving the deprecation map from BaseComponent, as it is conflicting with React's context when it is passed into the constructor.
@@ -38,17 +38,12 @@ export class BaseComponent<P extends IBaseProps, S> extends React.Component<P, S | |||
* @param {Object} deprecatedProps The map of deprecated prop names to new names, where the key is the old name and the |
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.
update comment?
@@ -38,17 +38,12 @@ export class BaseComponent<P extends IBaseProps, S> extends React.Component<P, S | |||
* @param {Object} deprecatedProps The map of deprecated prop names to new names, where the key is the old name and the | |||
* value is the new name. If a prop is removed rather than renamed, leave the value undefined. | |||
*/ | |||
constructor(props?: P, deprecationMap?: ISettingsMap<P>) { | |||
constructor(props?: P) { |
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.
take context parameter and pass along?
Addresses issue: #1356
This change is a subset of a much larger change, but this includes the important updates which are more general:
focus()
.) In order to access the actual "ref", I'm adding support for resolvingcomponentRef
to theBaseComponent
. This lets us pass through the callback to an inner component in decorator/HOC patterns. If you use BaseComponent as a base class, it will by default resolve it for you; you simply expose it in your Props definition. If you would like to avoid this being done because the inner component is doing it, you can set the protected_shouldUpdateComponentRef
bool to false which will bypass resolution at that component layer.Customizer
component andcustomizable
decorator for injection. These helpers will enable us to inject new default props into components without requiring every individual component to be subclassed.BaseComponent
constructor. Instead you can useBaseComponent
protected helpers_warnDeprecations
and_warnMutuallyExclusive
which will console.warn when deprecated things are being used.