mirror of
https://github.com/facebook/react.git
synced 2026-02-26 18:58:05 +00:00
This mode is going to be the new default in Flow going forward.
There was an unfortuante large number of suppressions in this update.
More on the changes can be found in this [Flow blog post](https://medium.com/flow-type/new-flow-language-rule-constrained-writes-4c70e375d190).
Added some of the required annotations using the provided codemod:
```sh
node_modules/.bin/flow codemod annotate-declarations --write .
```
ghstack-source-id: 0b168e1b23
Pull Request resolved: https://github.com/facebook/react/pull/25422
145 lines
4.0 KiB
JavaScript
145 lines
4.0 KiB
JavaScript
/**
|
|
* Copyright (c) Facebook, Inc. and its 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 type {ReactContext} from 'shared/ReactTypes';
|
|
|
|
import * as React from 'react';
|
|
import {createContext, useCallback, useContext, useEffect} from 'react';
|
|
import {createResource} from '../../cache';
|
|
import {BridgeContext, StoreContext} from '../context';
|
|
import {TreeStateContext} from './TreeContext';
|
|
import {separateDisplayNameAndHOCs} from 'react-devtools-shared/src/utils';
|
|
|
|
import type {OwnersList} from 'react-devtools-shared/src/backend/types';
|
|
import type {
|
|
Element,
|
|
SerializedElement,
|
|
} from 'react-devtools-shared/src/devtools/views/Components/types';
|
|
import type {Resource, Thenable} from '../../cache';
|
|
|
|
type Context = (id: number) => Array<SerializedElement> | null;
|
|
|
|
const OwnersListContext: ReactContext<Context> = createContext<Context>(
|
|
((null: any): Context),
|
|
);
|
|
OwnersListContext.displayName = 'OwnersListContext';
|
|
|
|
type ResolveFn = (ownersList: Array<SerializedElement> | null) => void;
|
|
type InProgressRequest = {
|
|
promise: Thenable<Array<SerializedElement>>,
|
|
resolveFn: ResolveFn,
|
|
};
|
|
|
|
const inProgressRequests: WeakMap<Element, InProgressRequest> = new WeakMap();
|
|
const resource: Resource<
|
|
Element,
|
|
Element,
|
|
Array<SerializedElement>,
|
|
> = createResource(
|
|
(element: Element) => {
|
|
const request = inProgressRequests.get(element);
|
|
if (request != null) {
|
|
// $FlowFixMe[incompatible-call] found when upgrading Flow
|
|
return request.promise;
|
|
}
|
|
|
|
let resolveFn:
|
|
| ResolveFn
|
|
| ((
|
|
result: Promise<Array<SerializedElement>> | Array<SerializedElement>,
|
|
) => void) = ((null: any): ResolveFn);
|
|
const promise = new Promise(resolve => {
|
|
resolveFn = resolve;
|
|
});
|
|
|
|
// $FlowFixMe[incompatible-call] found when upgrading Flow
|
|
inProgressRequests.set(element, {promise, resolveFn});
|
|
|
|
return promise;
|
|
},
|
|
(element: Element) => element,
|
|
{useWeakMap: true},
|
|
);
|
|
|
|
type Props = {
|
|
children: React$Node,
|
|
};
|
|
|
|
function OwnersListContextController({children}: Props): React.Node {
|
|
const bridge = useContext(BridgeContext);
|
|
const store = useContext(StoreContext);
|
|
const {ownerID} = useContext(TreeStateContext);
|
|
|
|
const read = useCallback(
|
|
(id: number) => {
|
|
const element = store.getElementByID(id);
|
|
if (element !== null) {
|
|
return resource.read(element);
|
|
} else {
|
|
return null;
|
|
}
|
|
},
|
|
[store],
|
|
);
|
|
|
|
useEffect(() => {
|
|
const onOwnersList = (ownersList: OwnersList) => {
|
|
const id = ownersList.id;
|
|
|
|
const element = store.getElementByID(id);
|
|
if (element !== null) {
|
|
const request = inProgressRequests.get(element);
|
|
if (request != null) {
|
|
inProgressRequests.delete(element);
|
|
|
|
request.resolveFn(
|
|
ownersList.owners === null
|
|
? null
|
|
: ownersList.owners.map(owner => {
|
|
const [
|
|
displayNameWithoutHOCs,
|
|
hocDisplayNames,
|
|
] = separateDisplayNameAndHOCs(owner.displayName, owner.type);
|
|
|
|
return {
|
|
...owner,
|
|
displayName: displayNameWithoutHOCs,
|
|
hocDisplayNames,
|
|
};
|
|
}),
|
|
);
|
|
}
|
|
}
|
|
};
|
|
|
|
bridge.addListener('ownersList', onOwnersList);
|
|
return () => bridge.removeListener('ownersList', onOwnersList);
|
|
}, [bridge, store]);
|
|
|
|
// This effect requests an updated owners list any time the selected owner changes
|
|
useEffect(() => {
|
|
if (ownerID !== null) {
|
|
const rendererID = store.getRendererIDForElement(ownerID);
|
|
if (rendererID !== null) {
|
|
bridge.send('getOwnersList', {id: ownerID, rendererID});
|
|
}
|
|
}
|
|
|
|
return () => {};
|
|
}, [bridge, ownerID, store]);
|
|
|
|
return (
|
|
<OwnersListContext.Provider value={read}>
|
|
{children}
|
|
</OwnersListContext.Provider>
|
|
);
|
|
}
|
|
|
|
export {OwnersListContext, OwnersListContextController};
|