Skip to content
This repository was archived by the owner on Mar 4, 2020. It is now read-only.

Commit 37e6c6b

Browse files
authored
feat(react-bindings): added useTelemetry and improved returned value of other hooks (#2257)
* -updates * -updated changelog * -removed animation from useStyles * -updated tests
1 parent f0c5ff7 commit 37e6c6b

File tree

22 files changed

+87
-58
lines changed

22 files changed

+87
-58
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
2929
- Allow `useRef` hook used for storing debugging data to be defined in any order with other hooks in functional components @layershifter, @mnajdova ([#2236](https://github.com/microsoft/fluent-ui-react/pull/2236))
3030
- Add `useStyles()` hook to use theming capabilities in custom components @layershifter, @mnajdova ([#2217](https://github.com/microsoft/fluent-ui-react/pull/2217))
3131
- Add optional wrapper function to `List` which can be used to inject custom scrollbars to `Dropdown` @jurokapsiar ([#2092](https://github.com/microsoft/fluent-ui-react/pull/2092))
32+
- Add `useTelemetry()` hook for adding telemetry information for the Fluent components and improve return types for the `useStyles` and `useStateManager` hooks @mnajdova ([#2257](https://github.com/microsoft/fluent-ui-react/pull/2257))
3233

3334
### Documentation
3435
- Add per-component performance charts @miroslavstastny ([#2240](https://github.com/microsoft/fluent-ui-react/pull/2240))

docs/src/prototypes/customToolbar/index.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
import * as _ from 'lodash'
22
import * as React from 'react'
33
import { KnobsSnippet } from '@fluentui/code-sandbox'
4+
import { Telemetry } from '@fluentui/react-bindings'
45
import {
56
KnobProvider,
67
useBooleanKnob,
78
useSelectKnob,
89
KnobInspector,
910
} from '@fluentui/docs-components'
10-
import { Provider, Flex, themes, mergeThemes, Telemetry } from '@fluentui/react'
11+
import { Provider, Flex, themes, mergeThemes } from '@fluentui/react'
1112

1213
import { darkThemeOverrides } from './darkThemeOverrides'
1314
import { highContrastThemeOverrides } from './highContrastThemeOverrides'

packages/react-bindings/README.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ const createInputManager: ManagerFactory<InputState, InputActions> = config =>
116116
})
117117

118118
const Input: React.FC<InputProps> = props => {
119-
const [state, actions] = useStateManager(createInputManager, {
119+
const { state, actions } = useStateManager(createInputManager, {
120120
mapPropsToInitialState: () => ({ value: props.defaultValue }),
121121
mapPropsToState: () => ({ value: props.value }),
122122
})
@@ -136,8 +136,8 @@ const Input: React.FC<InputProps> = props => {
136136
### Reference
137137

138138
```tsx
139-
const [state, actions] = useStateManager(createInputManager)
140-
const [state, actions] = useStateManager(
139+
const { state, actions } = useStateManager(createInputManager)
140+
const { state, actions } = useStateManager(
141141
managerFactory: ManagerFactory<State, Actions>,
142142
options: UseStateManagerOptions<Props>,
143143
)
@@ -164,7 +164,7 @@ type TextComponentProps = {
164164
const Text: React.FunctionComponent<TextComponentProps> = props => {
165165
const { className, children, color } = props
166166

167-
const [classes] = useStyles('Text', {
167+
const { classes } = useStyles('Text', {
168168
className: 'ui-text',
169169
mapPropsToStyles: () => ({ color }),
170170
})
@@ -176,7 +176,7 @@ const Text: React.FunctionComponent<TextComponentProps> = props => {
176176
### Reference
177177

178178
```tsx
179-
const [classes] = useStyles(
179+
const { classes } = useStyles(
180180
displayName: string,
181181
options: UseStylesOptions<Props>,
182182
)

packages/react-bindings/src/hooks/useStateManager.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@ type UseStateManagerOptions<State> = {
77
sideEffects?: SideEffect<State>[]
88
}
99

10+
type UseStateManagerResult<State, Actions> = {
11+
state: Readonly<State>
12+
actions: Readonly<Actions>
13+
}
14+
1015
const getDefinedProps = <Props extends Record<string, any>>(props: Props): Partial<Props> => {
1116
const definedProps: Partial<Props> = {}
1217

@@ -25,7 +30,7 @@ const useStateManager = <
2530
>(
2631
managerFactory: ManagerFactory<State, Actions>,
2732
options: UseStateManagerOptions<State> = {},
28-
): [Readonly<State>, Readonly<Actions>] => {
33+
): UseStateManagerResult<State, Actions> => {
2934
const {
3035
mapPropsToInitialState = () => ({} as Partial<State>),
3136
mapPropsToState = () => ({} as Partial<State>),
@@ -58,11 +63,14 @@ const useStateManager = <
5863
// https://github.com/facebook/react/issues/11527#issuecomment-360199710
5964

6065
if (process.env.NODE_ENV === 'production') {
61-
return [latestManager.current.state, latestManager.current.actions]
66+
return { state: latestManager.current.state, actions: latestManager.current.actions }
6267
}
6368

6469
// Object.freeze() is used only in dev-mode to avoid usage mistakes
65-
return [Object.freeze(latestManager.current.state), Object.freeze(latestManager.current.actions)]
70+
return {
71+
state: Object.freeze(latestManager.current.state),
72+
actions: Object.freeze(latestManager.current.actions),
73+
}
6674
}
6775

6876
export default useStateManager

packages/react-bindings/src/hooks/useStyles.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,11 @@ type UseStylesOptions<StyleProps extends PrimitiveProps> = {
2525
rtl?: boolean
2626
}
2727

28+
type UseStylesResult = {
29+
classes: ComponentSlotClasses
30+
styles: ComponentSlotStylesPrepared
31+
}
32+
2833
type InlineStyleProps<StyleProps> = {
2934
/** Additional CSS class name(s) to apply. */
3035
className?: string
@@ -48,7 +53,7 @@ const defaultContext: StylesContextValue<{ renderRule: RendererRenderRule }> = {
4853
const useStyles = <StyleProps extends PrimitiveProps>(
4954
displayName: string,
5055
options: UseStylesOptions<StyleProps>,
51-
): [ComponentSlotClasses, ComponentSlotStylesPrepared] => {
56+
): UseStylesResult => {
5257
const context: StylesContextValue<{ renderRule: RendererRenderRule }> =
5358
React.useContext(ThemeContext) || defaultContext
5459

@@ -79,7 +84,7 @@ const useStyles = <StyleProps extends PrimitiveProps>(
7984
_internal_resolvedComponentVariables: context._internal_resolvedComponentVariables,
8085
})
8186

82-
return [classes, resolvedStyles]
87+
return { classes, styles: resolvedStyles }
8388
}
8489

8590
export default useStyles

packages/react-bindings/src/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,8 @@ export { default as unstable_createAnimationStyles } from './styles/createAnimat
1818
export { default as unstable_getStyles } from './styles/getStyles'
1919
export * from './styles/types'
2020

21+
export { default as useTelemetry } from './telemetry/useTelemetry'
22+
export * from './telemetry/types'
23+
2124
export { default as getElementType } from './utils/getElementType'
2225
export { default as getUnhandledProps } from './utils/getUnhandledProps'

packages/react/src/utils/Telemetry.ts renamed to packages/react-bindings/src/telemetry/types.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,12 @@ type ComponentPerfStats = {
55
msMax: number
66
}
77

8-
export default class Telemetry {
8+
export type UseTelemetryResult = {
9+
setStart: () => void
10+
setEnd: () => void
11+
}
12+
13+
export class Telemetry {
914
performance: Record<string, ComponentPerfStats>
1015
enabled: boolean
1116

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import { Telemetry, UseTelemetryResult } from './types'
2+
3+
const useTelemetry = (
4+
displayName: string,
5+
telemetry: Telemetry | undefined,
6+
): UseTelemetryResult => {
7+
let start: number = -1
8+
let end: number = -1
9+
10+
const setStart = () => {
11+
start = telemetry && telemetry.enabled ? performance.now() : -1
12+
}
13+
14+
const setEnd = () => {
15+
if (telemetry && telemetry.enabled && start !== -1) {
16+
end = performance.now()
17+
const duration = end - start
18+
if (telemetry.performance[displayName]) {
19+
telemetry.performance[displayName].count++
20+
telemetry.performance[displayName].msTotal += duration
21+
telemetry.performance[displayName].msMin = Math.min(
22+
duration,
23+
telemetry.performance[displayName].msMin,
24+
)
25+
telemetry.performance[displayName].msMax = Math.max(
26+
duration,
27+
telemetry.performance[displayName].msMax,
28+
)
29+
} else {
30+
telemetry.performance[displayName] = {
31+
count: 1,
32+
msTotal: duration,
33+
msMin: duration,
34+
msMax: duration,
35+
}
36+
}
37+
}
38+
}
39+
40+
return { setStart, setEnd }
41+
}
42+
43+
export default useTelemetry

packages/react-bindings/test/hooks/useDispatchEffect-test.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ const TestComponent: React.FunctionComponent<TestComponentProps> = props => {
3737
}
3838
},
3939
)
40-
const [state, actions] = useStateManager(createTestManager, {
40+
const { state, actions } = useStateManager(createTestManager, {
4141
mapPropsToInitialState: () => ({ value: props.defaultValue }),
4242
mapPropsToState: () => ({ value: props.value }),
4343
sideEffects: [dispatchEffect],

packages/react-bindings/test/hooks/useStateManager-test.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ type TestComponentProps = Partial<TestState> & {
3333
}
3434

3535
const TestComponent: React.FunctionComponent<TestComponentProps> = props => {
36-
const [state, actions] = useStateManager(createTestManager, {
36+
const { state, actions } = useStateManager(createTestManager, {
3737
mapPropsToInitialState: () => ({
3838
open: props.defaultOpen,
3939
value: props.defaultValue,

packages/react-bindings/test/hooks/useStyles-test.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ type TestComponentProps = {
1616
const TestComponent: React.FunctionComponent<TestComponentProps> = props => {
1717
const { className, color, styles, variables } = props
1818

19-
const [classes] = useStyles('Test', {
19+
const { classes } = useStyles('Test', {
2020
className: 'ui-test',
2121
mapPropsToStyles: () => ({ color }),
2222
mapPropsToInlineStyles: () => ({ className, styles, variables }),

packages/react/src/components/Animation/Animation.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,6 @@ class Animation extends UIComponent<WithAsProp<AnimationProps>, any> {
8989
static propTypes = {
9090
...commonPropTypes.createCommon({
9191
accessibility: false,
92-
animated: false,
9392
content: false,
9493
children: 'element',
9594
}),

packages/react/src/components/MenuButton/MenuButton.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,6 @@ export default class MenuButton extends AutoControlledComponent<MenuButtonProps,
113113

114114
static propTypes = {
115115
...commonPropTypes.createCommon({
116-
animated: false,
117116
as: true,
118117
content: false,
119118
}),

packages/react/src/components/Popup/Popup.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,6 @@ export default class Popup extends AutoControlledComponent<PopupProps, PopupStat
145145

146146
static propTypes = {
147147
...commonPropTypes.createCommon({
148-
animated: false,
149148
as: false,
150149
content: false,
151150
}),

packages/react/src/components/Portal/Portal.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,6 @@ class Portal extends AutoControlledComponent<PortalProps, PortalState> {
9191
static propTypes = {
9292
...commonPropTypes.createCommon({
9393
accessibility: false,
94-
animated: false,
9594
as: false,
9695
className: false,
9796
styled: false,

packages/react/src/components/Portal/PortalInner.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ class PortalInner extends React.Component<PortalInnerProps> {
3535
static propTypes = {
3636
...commonPropTypes.createCommon({
3737
accessibility: false,
38-
animated: false,
3938
as: false,
4039
className: false,
4140
content: false,

packages/react/src/components/Provider/Provider.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { IStyle } from 'fela'
22
import * as _ from 'lodash'
3-
import { Renderer } from '@fluentui/react-bindings'
3+
import { Renderer, Telemetry } from '@fluentui/react-bindings'
44
import * as customPropTypes from '@fluentui/react-proptypes'
55
import {
66
mergeSiteVariables,
@@ -28,7 +28,6 @@ import {
2828
withSafeTypeForAs,
2929
} from '../../types'
3030
import mergeContexts from '../../utils/mergeProviderContexts'
31-
import Telemetry from '../../utils/Telemetry'
3231

3332
export interface ProviderProps extends ChildrenComponentProps {
3433
renderer?: Renderer

packages/react/src/components/Tooltip/Tooltip.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,6 @@ export default class Tooltip extends AutoControlledComponent<TooltipProps, Toolt
111111

112112
static propTypes = {
113113
...commonPropTypes.createCommon({
114-
animated: false,
115114
as: false,
116115
content: false,
117116
}),

packages/react/src/types.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
1-
import { StylesContextInputValue, StylesContextValue } from '@fluentui/react-bindings'
1+
import { StylesContextInputValue, StylesContextValue, Telemetry } from '@fluentui/react-bindings'
22
import * as React from 'react'
33

4-
import Telemetry from './utils/Telemetry'
5-
64
// ========================================================
75
// Utilities
86
// ========================================================

packages/react/src/utils/commonPropTypes.ts

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import * as PropTypes from 'prop-types'
33

44
export interface CreateCommonConfig {
55
accessibility?: boolean
6-
animated?: boolean
76
children?: boolean | 'node' | 'element'
87
as?: boolean
98
className?: boolean
@@ -15,7 +14,6 @@ export interface CreateCommonConfig {
1514
export const createCommon = (config: CreateCommonConfig = {}) => {
1615
const {
1716
accessibility = true,
18-
animated = true,
1917
as = true,
2018
children = 'node',
2119
className = true,
@@ -27,9 +25,6 @@ export const createCommon = (config: CreateCommonConfig = {}) => {
2725
...(accessibility && {
2826
accessibility: customPropTypes.accessibility,
2927
}),
30-
...(animated && {
31-
animation: customPropTypes.animation,
32-
}),
3328
...(as && {
3429
as: PropTypes.elementType,
3530
}),

packages/react/src/utils/index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,3 @@ export module commonPropTypes {
4343
export type CreateCommonConfig = CreateCommonConfigLocal
4444
export const createCommon = createCommonLocal
4545
}
46-
export { default as Telemetry } from './Telemetry'

packages/react/src/utils/renderComponent.tsx

Lines changed: 4 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {
1010
ReactAccessibilityBehavior,
1111
unstable_getAccessibility as getAccessibility,
1212
unstable_getStyles as getStyles,
13+
useTelemetry,
1314
} from '@fluentui/react-bindings'
1415
import {
1516
emptyTheme,
@@ -24,7 +25,6 @@ import * as React from 'react'
2425

2526
import { Props, ProviderContextPrepared } from '../types'
2627
import logProviderMissingWarning from './providerMissingHandler'
27-
import Telemetry from './Telemetry'
2828

2929
export interface RenderResultConfig<P> {
3030
ElementType: React.ElementType<P>
@@ -69,10 +69,10 @@ const renderComponent = <P extends {}>(
6969
logProviderMissingWarning()
7070
}
7171

72-
const { telemetry = undefined as Telemetry } = context || {}
72+
const { setStart, setEnd } = useTelemetry(displayName, context.telemetry)
7373
const rtl = context.rtl || false
7474

75-
const startTime = telemetry && telemetry.enabled ? performance.now() : 0
75+
setStart()
7676

7777
const ElementType = getElementType(props) as React.ReactType<P>
7878
const unhandledProps = getUnhandledProps(handledProps, props)
@@ -109,29 +109,7 @@ const renderComponent = <P extends {}>(
109109
}
110110
let wrapInFocusZone: (element: React.ReactElement) => React.ReactElement = element => element
111111

112-
if (telemetry && telemetry.enabled) {
113-
const duration = performance.now() - startTime
114-
115-
if (telemetry.performance[displayName]) {
116-
telemetry.performance[displayName].count++
117-
telemetry.performance[displayName].msTotal += duration
118-
telemetry.performance[displayName].msMin = Math.min(
119-
duration,
120-
telemetry.performance[displayName].msMin,
121-
)
122-
telemetry.performance[displayName].msMax = Math.max(
123-
duration,
124-
telemetry.performance[displayName].msMax,
125-
)
126-
} else {
127-
telemetry.performance[displayName] = {
128-
count: 1,
129-
msTotal: duration,
130-
msMin: duration,
131-
msMax: duration,
132-
}
133-
}
134-
}
112+
setEnd()
135113

136114
if (accessibility.focusZone && accessibility.focusZone.mode === FocusZoneMode.Wrap) {
137115
wrapInFocusZone = element =>

0 commit comments

Comments
 (0)