/** * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * * @flow */ import * as React from 'react'; import {useContext} from 'react'; import {ProfilerContext} from './ProfilerContext'; import {StoreContext} from '../context'; import styles from './WhatChanged.css'; function hookIndicesToString(indices: Array): string { // This is debatable but I think 1-based might ake for a nicer UX. const numbers = indices.map(value => value + 1); switch (numbers.length) { case 0: return 'No hooks changed'; case 1: return `Hook ${numbers[0]} changed`; case 2: return `Hooks ${numbers[0]} and ${numbers[1]} changed`; default: return `Hooks ${numbers.slice(0, numbers.length - 1).join(', ')} and ${ numbers[numbers.length - 1] } changed`; } } type Props = { fiberID: number, }; export default function WhatChanged({fiberID}: Props): React.Node { const {profilerStore} = useContext(StoreContext); const {rootID, selectedCommitIndex} = useContext(ProfilerContext); // TRICKY // Handle edge case where no commit is selected because of a min-duration filter update. // If the commit index is null, suspending for data below would throw an error. // TODO (ProfilerContext) This check should not be necessary. if (selectedCommitIndex === null) { return null; } const {changeDescriptions} = profilerStore.getCommitData( ((rootID: any): number), selectedCommitIndex, ); if (changeDescriptions === null) { return null; } const changeDescription = changeDescriptions.get(fiberID); if (changeDescription == null) { return null; } const {context, didHooksChange, hooks, isFirstMount, props, state} = changeDescription; if (isFirstMount) { return (
This is the first time the component rendered.
); } const changes = []; if (context === true) { changes.push(
• Context changed
, ); } else if ( typeof context === 'object' && context !== null && context.length !== 0 ) { changes.push(
• Context changed: {context.map(key => ( {key} ))}
, ); } if (didHooksChange) { if (Array.isArray(hooks)) { changes.push(
• {hookIndicesToString(hooks)}
, ); } else { changes.push(
• Hooks changed
, ); } } if (props !== null && props.length !== 0) { changes.push(
• Props changed: {props.map(key => ( {key} ))}
, ); } if (state !== null && state.length !== 0) { changes.push(
• State changed: {state.map(key => ( {key} ))}
, ); } if (changes.length === 0) { changes.push(
The parent component rendered.
, ); } return (
{changes}
); }