Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions ghdocs/BESTPRACTICES.md
Original file line number Diff line number Diff line change
Expand Up @@ -187,10 +187,6 @@ Note that it's very critical you do NOT inline the functions in render! This cau
is recreated. If you do this, react will call your function with null to clear it, and then render, and then once complete, will
call it again with the element. This creates timing issues where your ref may be null when you didn't expect.

See example here that illustates refs being re-evaluated:

http://codepen.io/dzearing/pen/WGZOaR

## Use unique keys for items in a mapped array, avoid indexes for keys

```typescript
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,14 +83,13 @@ export class Breadcrumb extends BaseComponent<IBreadcrumbProps, any> {
return (
<div
className={ css('ms-Breadcrumb', className, styles.root) }
ref='renderingArea'
role='navigation'
aria-label={ ariaLabel }
>
<FocusZone direction={ FocusZoneDirection.horizontal } >
<ol className={ css('ms-Breadcrumb-list', styles.list) }>
{ renderedOverflowItems && renderedOverflowItems.length !== 0 && (
<li className={ css('ms-Breadcrumb-overflow', styles.overflow) } key={ OVERFLOW_KEY } ref={ OVERFLOW_KEY }>
<li className={ css('ms-Breadcrumb-overflow', styles.overflow) } key={ OVERFLOW_KEY }>
<IconButton
className={ css('ms-Breadcrumb-overflowButton', styles.overflowButton) }
iconProps={ { iconName: 'More' } }
Expand All @@ -110,7 +109,7 @@ export class Breadcrumb extends BaseComponent<IBreadcrumbProps, any> {
) }
{ renderedItems.map(
(item, index) => (
<li className={ css('ms-Breadcrumb-listItem', styles.listItem) } key={ item.key || String(index) } ref={ item.key || String(index) }>
<li className={ css('ms-Breadcrumb-listItem', styles.listItem) } key={ item.key || String(index) }>
{ onRenderItem(item, this._onRenderItem) }
<Icon
className={ css('ms-Breadcrumb-chevron', styles.chevron) }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,12 +71,9 @@ export class Calendar extends BaseComponent<ICalendarProps, ICalendarState> impl
workWeekDays: defaultWorkWeekDays
};

public refs: {
[key: string]: React.ReactInstance;
root: HTMLElement;
dayPicker: CalendarDay;
monthPicker: CalendarMonth;
};
public root: HTMLElement;
public dayPicker: CalendarDay;
public monthPicker: CalendarMonth;

private _focusOnUpdate: boolean;

Expand Down Expand Up @@ -116,10 +113,10 @@ export class Calendar extends BaseComponent<ICalendarProps, ICalendarState> impl
public componentDidUpdate() {
if (this._focusOnUpdate) {
// if the day picker is shown, focus on it
if (this.refs.dayPicker) {
this.refs.dayPicker.focus();
} else if (this.refs.monthPicker) {
this.refs.monthPicker.focus();
if (this.dayPicker) {
this.dayPicker.focus();
} else if (this.monthPicker) {
this.monthPicker.focus();
}
this._focusOnUpdate = false;
}
Expand All @@ -134,7 +131,7 @@ export class Calendar extends BaseComponent<ICalendarProps, ICalendarState> impl
const overlayedWithButton = showMonthPickerAsOverlay && showGoToToday;

return (
<div className={ css(rootClass, styles.root) } ref='root' role='application'>
<div className={ css(rootClass, styles.root) } ref={ this._resolveRef('root') } role='application'>
<div
className={ css(
'ms-DatePicker-picker ms-DatePicker-picker--opened ms-DatePicker-picker--focused',
Expand Down Expand Up @@ -170,7 +167,7 @@ export class Calendar extends BaseComponent<ICalendarProps, ICalendarState> impl
minDate={ minDate }
maxDate={ maxDate }
workWeekDays={ this.props.workWeekDays }
ref='dayPicker'
ref={ this._resolveRef('_dayPicker') }
/>
}

Expand All @@ -185,7 +182,7 @@ export class Calendar extends BaseComponent<ICalendarProps, ICalendarState> impl
dateTimeFormatter={ this.props.dateTimeFormatter! }
minDate={ minDate }
maxDate={ maxDate }
ref='monthPicker'
ref={ this._resolveRef('monthPicker') }
/> }

{ showGoToToday &&
Expand All @@ -208,8 +205,8 @@ export class Calendar extends BaseComponent<ICalendarProps, ICalendarState> impl
}

public focus() {
if (this.refs.dayPicker) {
this.refs.dayPicker.focus();
if (this.dayPicker) {
this.dayPicker.focus();
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,7 @@ export class ColorRectangle extends BaseComponent<IColorRectangleProps, IColorPi
minSize: 220
};

public refs: {
[key: string]: React.ReactInstance;
root: HTMLElement;
};
private root: HTMLDivElement;

constructor(props: IColorRectangleProps) {
super(props);
Expand Down Expand Up @@ -71,7 +68,7 @@ export class ColorRectangle extends BaseComponent<IColorRectangleProps, IColorPi
const { color, fullColorString } = this.state;

return (
<div ref='root' className={ css('ms-ColorPicker-colorRect', styles.colorRect) } style={ { minWidth: minSize, minHeight: minSize, backgroundColor: fullColorString } } onMouseDown={ this._onMouseDown }>
<div ref={ this._resolveRef('_root') } className={ css('ms-ColorPicker-colorRect', styles.colorRect) } style={ { minWidth: minSize, minHeight: minSize, backgroundColor: fullColorString } } onMouseDown={ this._onMouseDown }>
<div className={ css('ms-ColorPicker-light', styles.light) } />
<div className={ css('ms-ColorPicker-dark', styles.dark) } />
<div className={ css('ms-ColorPicker-thumb', styles.thumb) } style={ { left: color!.s + '%', top: (MAX_COLOR_VALUE - color!.v) + '%', backgroundColor: color!.str } } />
Expand All @@ -90,7 +87,7 @@ export class ColorRectangle extends BaseComponent<IColorRectangleProps, IColorPi
@autobind
private _onMouseMove(ev: React.MouseEvent<HTMLElement>) {
const { color, onSVChanged } = this.props;
const rectSize = this.refs.root.getBoundingClientRect();
const rectSize = this.root.getBoundingClientRect();

const sPercentage = (ev.clientX - rectSize.left) / rectSize.width;
const vPercentage = (ev.clientY - rectSize.top) / rectSize.height;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,7 @@ export class ColorSlider extends BaseComponent<IColorSliderProps, IColorSliderSt
value: 0
};

public refs: {
[key: string]: React.ReactInstance;
root: HTMLElement;
};
private _root: HTMLElement;

constructor(props: IColorSliderProps) {
super(props);
Expand Down Expand Up @@ -65,7 +62,7 @@ export class ColorSlider extends BaseComponent<IColorSliderProps, IColorSliderSt

return (
<div
ref='root'
ref={ this._resolveRef('_root') }
className={ css(
'ms-ColorPicker-slider',
styles.slider,
Expand All @@ -91,7 +88,7 @@ export class ColorSlider extends BaseComponent<IColorSliderProps, IColorSliderSt
@autobind
private _onMouseMove(ev: React.MouseEvent<HTMLElement>) {
const { onChanged, minValue, maxValue } = this.props;
const rectSize = this.refs.root.getBoundingClientRect();
const rectSize = this._root.getBoundingClientRect();

const currentPercentage = (ev.clientX - rectSize.left) / rectSize.width;
const newValue = Math.min(maxValue!, Math.max(minValue!, currentPercentage * maxValue!));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,10 +89,7 @@ export class ComboBox extends BaseComponent<IComboBoxProps, IComboBoxState> {
buttonIconProps: { iconName: 'ChevronDown' }
};

public refs: {
[key: string]: React.ReactInstance,
root: HTMLElement
};
private _root: HTMLElement;

// The input aspect of the comboBox
private _comboBox: Autofill;
Expand Down Expand Up @@ -306,7 +303,7 @@ export class ComboBox extends BaseComponent<IComboBoxProps, IComboBoxState> {
);

return (
<div { ...divProps } ref='root' className={ this._classNames.container }>
<div { ...divProps } ref={ this._resolveRef('_root') } className={ this._classNames.container }>
{ label && (
<Label id={ id + '-label' } disabled={ disabled } required={ required } htmlFor={ id + '-input' } className={ this._classNames.label }>{ label }</Label>
) }
Expand Down Expand Up @@ -784,7 +781,7 @@ export class ComboBox extends BaseComponent<IComboBoxProps, IComboBoxState> {
// inside the comboBox root or the comboBox menu since
// it we are not really bluring from the whole comboBox
if (event.relatedTarget &&
(this.refs.root && this.refs.root.contains(event.relatedTarget as HTMLElement) ||
(this._root && this._root.contains(event.relatedTarget as HTMLElement) ||
this._comboBoxMenu && this._comboBoxMenu.contains(event.relatedTarget as HTMLElement))) {
event.preventDefault();
event.stopPropagation();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,15 @@ export class CommandBar extends BaseComponent<ICommandBarProps, ICommandBarState

public refs: {
[key: string]: React.ReactInstance;
commandSurface: HTMLElement;
farCommandSurface: HTMLElement;
commandBarRegion: HTMLElement;
searchSurface: HTMLElement;
focusZone: FocusZone;
};

private _searchSurface: HTMLElement;
private _commandSurface: HTMLElement;
private _commandBarRegion: HTMLElement;
private _farCommandSurface: HTMLElement;
private _focusZone: FocusZone;
private _overflow: HTMLElement;

private _id: string;
private _overflowWidth: number;
private _commandItemWidths: { [key: string]: number } | null;
Expand Down Expand Up @@ -88,7 +90,7 @@ export class CommandBar extends BaseComponent<ICommandBarProps, ICommandBarState

if (isSearchBoxVisible) {
searchBox = (
<div className={ css('ms-CommandBarSearch', styles.search) } ref='searchSurface'>
<div className={ css('ms-CommandBarSearch', styles.search) } ref={ this._resolveRef('_searchSurface') }>
<input className={ css('ms-CommandBarSearch-input', styles.searchInput) } type='text' placeholder={ searchPlaceholderText } />
<div
className={ css(
Expand All @@ -115,14 +117,14 @@ export class CommandBar extends BaseComponent<ICommandBarProps, ICommandBarState
let posInSet = 1;

return (
<div className={ css('ms-CommandBar', styles.root, className) } ref='commandBarRegion'>
<div className={ css('ms-CommandBar', styles.root, className) } ref={ this._resolveRef('_commandBarRegion') }>
{ searchBox }
<FocusZone ref='focusZone' className={ styles.container } direction={ FocusZoneDirection.horizontal } role='menubar' >
<div className={ css('ms-CommandBar-primaryCommands', styles.primaryCommands) } ref='commandSurface'>
<FocusZone ref={ this._resolveRef('_focusZone') } className={ styles.container } direction={ FocusZoneDirection.horizontal } role='menubar' >
<div className={ css('ms-CommandBar-primaryCommands', styles.primaryCommands) } ref={ this._resolveRef('_commandSurface') }>
{ renderedItems!.map(item => (
this._renderItemInCommandBar(item, posInSet++, setSize, expandedMenuItemKey!)
)).concat((renderedOverflowItems && renderedOverflowItems.length) ? [
<div className={ css('ms-CommandBarItem', styles.item) } key={ OVERFLOW_KEY } ref={ OVERFLOW_KEY }>
<div className={ css('ms-CommandBarItem', styles.item) } key={ OVERFLOW_KEY } ref={ this._resolveRef('_overflow') }>
<button
type='button'
id={ this._id + OVERFLOW_KEY }
Expand All @@ -143,7 +145,7 @@ export class CommandBar extends BaseComponent<ICommandBarProps, ICommandBarState
</div>
] : []) }
</div>
<div className={ css('ms-CommandBar-sideCommands', styles.sideCommands) } ref='farCommandSurface'>
<div className={ css('ms-CommandBar-sideCommands', styles.sideCommands) } ref={ this._resolveRef('_farCommandSurface') }>
{ renderedFarItems!.map(item => (
this._renderItemInCommandBar(item, posInSet++, setSize, expandedMenuItemKey!, true)
)) }
Expand All @@ -165,7 +167,7 @@ export class CommandBar extends BaseComponent<ICommandBarProps, ICommandBarState
}

public focus() {
this.refs.focusZone.focus();
this._focusZone.focus();
}

private _renderItemInCommandBar(item: ICommandBarItemProps, posInSet: number, setSize: number, expandedMenuItemKey: string, isFarItem?: boolean) {
Expand Down Expand Up @@ -305,7 +307,7 @@ export class CommandBar extends BaseComponent<ICommandBarProps, ICommandBarState

private _updateItemMeasurements() {
// the generated width for overflow is 35 in chrome, 38 in IE, but the actual value is 41.5
if (this.refs[OVERFLOW_KEY] || (this.props.overflowItems && this.props.overflowItems.length)) {
if (this._overflow || (this.props.overflowItems && this.props.overflowItems.length)) {
this._overflowWidth = OVERFLOW_WIDTH;
} else {
this._overflowWidth = 0;
Expand All @@ -330,10 +332,10 @@ export class CommandBar extends BaseComponent<ICommandBarProps, ICommandBarState

private _updateRenderedItems() {
const { items, overflowItems } = this.props;
const commandSurface = this.refs.commandSurface;
const farCommandSurface = this.refs.farCommandSurface;
const commandBarRegion = this.refs.commandBarRegion;
const searchSurface = this.refs.searchSurface;
const commandSurface = this._commandSurface;
const farCommandSurface = this._farCommandSurface;
const commandBarRegion = this._commandBarRegion;
const searchSurface = this._searchSurface;
const renderedItems = [...items];
let renderedOverflowItems = overflowItems;
let consumedWidth = 0;
Expand Down Expand Up @@ -416,7 +418,7 @@ export class CommandBar extends BaseComponent<ICommandBarProps, ICommandBarState

@autobind
private _onContextMenuDismiss(ev?: any) {
if (!ev || !ev.relatedTarget || !this.refs.commandSurface.contains(ev.relatedTarget as HTMLElement)) {
if (!ev || !ev.relatedTarget || !this._commandSurface.contains(ev.relatedTarget as HTMLElement)) {
const { contextualMenuProps } = this.state;

if (contextualMenuProps && contextualMenuProps.onDismiss) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,6 @@ const DIRECTION_OPTIONS = [{ key: DirectionalHint.topLeftEdge, text: 'Top Left E
];

export class ContextualMenuDirectionalExample extends React.Component<{}, IContextualMenuDirectionalExampleState> {
public refs: {
[key: string]: React.ReactInstance;
menuButton: HTMLElement;
gapSize: TextField;
};

public constructor(props: {}) {
super(props);

Expand Down Expand Up @@ -95,7 +89,7 @@ export class ContextualMenuDirectionalExample extends React.Component<{}, IConte
/>
}
</div>
<div className='ms-ContextualMenuDirectionalExample-buttonArea' ref='menuButton'>
<div className='ms-ContextualMenuDirectionalExample-buttonArea'>
<DefaultButton
text='Show context menu'
menuProps={ {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,10 +82,7 @@ export class DetailsHeader extends BaseComponent<IDetailsHeaderProps, IDetailsHe
collapseAllVisibility: CollapseAllVisibility.visible
};

public refs: {
[key: string]: React.ReactInstance;
root: FocusZone;
};
private _root: FocusZone;

private _id: string;

Expand All @@ -108,7 +105,7 @@ export class DetailsHeader extends BaseComponent<IDetailsHeaderProps, IDetailsHe

this._events.on(selection, SELECTION_CHANGE, this._onSelectionChanged);

const rootElement = ReactDOM.findDOMNode(this.refs.root);
const rootElement = ReactDOM.findDOMNode(this._root);

// We need to use native on this to avoid MarqueeSelection from handling the event before us.
this._events.on(rootElement, 'mousedown', this._onRootMouseDown);
Expand Down Expand Up @@ -145,7 +142,7 @@ export class DetailsHeader extends BaseComponent<IDetailsHeaderProps, IDetailsHe
(selectAllVisibility === SelectAllVisibility.hidden) && ('is-selectAllHidden ' + styles.rootIsSelectAllHidden),
(!!columnResizeDetails && isSizing) && 'is-resizingColumn'
) }
ref='root'
ref={ this._resolveRef('_root') }
onMouseMove={ this._onRootMouseMove }
data-automationid='DetailsHeader'
direction={ FocusZoneDirection.horizontal }
Expand Down Expand Up @@ -329,7 +326,7 @@ export class DetailsHeader extends BaseComponent<IDetailsHeaderProps, IDetailsHe

/** Set focus to the active thing in the focus area. */
public focus(): boolean {
return this.refs.root.focus();
return this._root.focus();
}

private _renderColumnSizer(columnIndex: number) {
Expand Down Expand Up @@ -501,7 +498,7 @@ export class DetailsHeader extends BaseComponent<IDetailsHeaderProps, IDetailsHe
// use buttons property here since ev.button in some edge case is not upding well during the move.
// but firefox doesn't support it, so we set the default value when it is not defined.
buttons
} = ev;
} = ev;
const { onColumnIsSizingChanged, onColumnResized, columns } = this.props;
const { columnResizeDetails } = this.state;

Expand Down
Loading