mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Allow injecting looser VirtualizedList
Summary: VirtualizedList_EXPERIMENTAL has a different flow signature from VirtualizedList. This does not cause an error in unit tests, which are untyped, but prevents injecting VirtualizedList_EXPERIMENTAL via the current API from flowtype. This diff updates the injection interface to allow a more relaxed type, validating safety at runtime. Changelog: [Internal][Changed] - Allow injecting looser VirtualizedList Reviewed By: javache Differential Revision: D38143682 fbshipit-source-id: 054bbc5092823f4e4413d69d3d72a7ecdd71a6a2
This commit is contained in:
committed by
Facebook GitHub Bot
parent
ccbfdd7167
commit
f8e1fedf3d
@@ -28,6 +28,7 @@ import {
|
||||
computeWindowedRenderLimits,
|
||||
keyExtractor as defaultKeyExtractor,
|
||||
} from './VirtualizeUtils';
|
||||
import * as VirtualizedListInjection from './VirtualizedListInjection';
|
||||
import * as React from 'react';
|
||||
|
||||
const RefreshControl = require('../Components/RefreshControl/RefreshControl');
|
||||
@@ -302,7 +303,7 @@ type OptionalProps = {|
|
||||
legacyImplementation?: empty,
|
||||
|};
|
||||
|
||||
type Props = {|
|
||||
export type Props = {|
|
||||
...React.ElementConfig<typeof ScrollView>,
|
||||
...RequiredProps,
|
||||
...OptionalProps,
|
||||
@@ -2217,5 +2218,6 @@ const styles = StyleSheet.create({
|
||||
},
|
||||
});
|
||||
|
||||
module.exports = (require('./VirtualizedListInjection').default
|
||||
.unstable_VirtualizedList ?? VirtualizedList: typeof VirtualizedList);
|
||||
module.exports = (VirtualizedListInjection.getOrDefault(
|
||||
VirtualizedList,
|
||||
): typeof VirtualizedList);
|
||||
|
||||
@@ -4,13 +4,69 @@
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @flow
|
||||
* @flow strict-local
|
||||
* @format
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
import typeof VirtualizedList from './VirtualizedList';
|
||||
|
||||
export default {
|
||||
unstable_VirtualizedList: (null: ?VirtualizedList),
|
||||
};
|
||||
import * as React from 'react';
|
||||
import type VirtualizedList from './VirtualizedList';
|
||||
import type {Props as VirtualizedListProps} from './VirtualizedList';
|
||||
import invariant from 'invariant';
|
||||
|
||||
export type ListImplementation = React.ComponentType<VirtualizedListProps> &
|
||||
interface {};
|
||||
|
||||
/**
|
||||
* Global override to the VirtualizedList implementation used when imported
|
||||
*/
|
||||
let injection: ?ListImplementation;
|
||||
let retrieved = false;
|
||||
|
||||
export function inject(listImplementation: ListImplementation): void {
|
||||
invariant(
|
||||
!retrieved,
|
||||
'VirtualizedListInjection.inject() called after the injection was already retrieved',
|
||||
);
|
||||
injection = listImplementation;
|
||||
}
|
||||
|
||||
export function getOrDefault(
|
||||
defaultImplementation: Class<VirtualizedList>,
|
||||
): Class<VirtualizedList> {
|
||||
retrieved = true;
|
||||
return injection
|
||||
? verifyVirtualizedList(injection, defaultImplementation)
|
||||
: defaultImplementation;
|
||||
}
|
||||
|
||||
function verifyVirtualizedList(
|
||||
injectedImplementation: ListImplementation,
|
||||
defaultImplementation: Class<VirtualizedList>,
|
||||
): Class<VirtualizedList> {
|
||||
// The original VirtualizedList marks method as "private by convention" by
|
||||
// prefixing with underscore. These methods may still be called at runtime
|
||||
// by tests or other internals, so they cannot be truly private, and will be
|
||||
// included in the Flow type of VirtualizedList.
|
||||
// Allow the injection to have different private methods by allowing a loose
|
||||
// Flow type, but check at runtime that the set of public properties matches.
|
||||
if (__DEV__) {
|
||||
for (const field of Object.keys(defaultImplementation)) {
|
||||
if (isPublicField(field)) {
|
||||
invariant(
|
||||
injectedImplementation.hasOwnProperty(field),
|
||||
`VirtualizedList injection missing field: "${field}"`,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// $FlowExpectedError
|
||||
return injectedImplementation;
|
||||
}
|
||||
|
||||
function isPublicField(fieldName: string): boolean {
|
||||
// Respect JSTransform public methods by double underscore (D33982339)
|
||||
return fieldName.length > 0 && (fieldName[0] !== '_' || fieldName[1] === '_');
|
||||
}
|
||||
|
||||
@@ -307,7 +307,7 @@ type OptionalProps = {|
|
||||
legacyImplementation?: empty,
|
||||
|};
|
||||
|
||||
type Props = {|
|
||||
export type Props = {|
|
||||
...React.ElementConfig<typeof ScrollView>,
|
||||
...RequiredProps,
|
||||
...OptionalProps,
|
||||
|
||||
@@ -12,15 +12,14 @@
|
||||
|
||||
import React from 'react';
|
||||
import ReactTestRenderer from 'react-test-renderer';
|
||||
import VirtualizedListInjection from '../VirtualizedListInjection';
|
||||
import * as VirtualizedListInjection from '../VirtualizedListInjection';
|
||||
import VirtualizedList_EXPERIMENTAL from '../VirtualizedList_EXPERIMENTAL';
|
||||
|
||||
const useExperimentalList =
|
||||
process.env.USE_EXPERIMENTAL_VIRTUALIZEDLIST === 'true';
|
||||
|
||||
if (useExperimentalList) {
|
||||
VirtualizedListInjection.unstable_VirtualizedList =
|
||||
VirtualizedList_EXPERIMENTAL;
|
||||
VirtualizedListInjection.inject(VirtualizedList_EXPERIMENTAL);
|
||||
}
|
||||
|
||||
const VirtualizedList = require('../VirtualizedList');
|
||||
|
||||
Reference in New Issue
Block a user