[change] Add usePlatformMethods to implement instance methods

A hook equivalent for implementing "native methods" on refs to elements backed
by function components.
This commit is contained in:
Nicolas Gallagher
2020-02-03 10:50:30 -08:00
parent 51ac083d56
commit a2cccaf528
5 changed files with 89 additions and 10 deletions
+2 -2
View File
@@ -77,7 +77,7 @@ const UIManager = {
measureLayout(node, relativeToNativeNode, onSuccess); measureLayout(node, relativeToNativeNode, onSuccess);
}, },
updateView(node, props, component /* only needed to surpress React errors in development */) { updateView(node, props) {
for (const prop in props) { for (const prop in props) {
if (!Object.prototype.hasOwnProperty.call(props, prop)) { if (!Object.prototype.hasOwnProperty.call(props, prop)) {
continue; continue;
@@ -86,7 +86,7 @@ const UIManager = {
const value = props[prop]; const value = props[prop];
switch (prop) { switch (prop) {
case 'style': { case 'style': {
setValueForStyles(node, value, component._reactInternalInstance); setValueForStyles(node, value);
break; break;
} }
case 'class': case 'class':
@@ -0,0 +1,75 @@
/**
* Copyright (c) Nicolas Gallagher.
*
* 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 { GenericStyleProp } from '../types';
import type { ElementRef } from 'react';
import UIManager from '../exports/UIManager';
import createDOMProps from '../modules/createDOMProps';
import { useImperativeHandle, useRef } from 'react';
export default function usePlatformMethods(
hostRef: ElementRef<any>,
ref: ElementRef<any>,
classList: Array<string>,
style: GenericStyleProp<any>
) {
const previousStyle = useRef(null);
useImperativeHandle(
ref,
() => {
return {
blur() {
UIManager.blur(hostRef.current);
},
focus() {
UIManager.focus(hostRef.current);
},
measure(callback) {
UIManager.measure(hostRef.current, callback);
},
measureLayout(relativeToNativeNode, onFail, onSuccess) {
UIManager.measureLayout(hostRef.current, relativeToNativeNode, onFail, onSuccess);
},
measureInWindow(callback) {
UIManager.measureInWindow(hostRef.current, callback);
},
setNativeProps(nativeProps) {
const node = hostRef.current;
if (node && nativeProps) {
const domProps = createDOMProps(null, {
...nativeProps,
classList: [nativeProps.className, classList],
style: [style, nativeProps.style]
});
const nextDomStyle = domProps.style;
if (previousStyle.current != null) {
if (domProps.style == null) {
domProps.style = {};
}
for (const styleName in previousStyle.current) {
if (domProps.style[styleName] == null) {
domProps.style[styleName] = '';
}
}
}
previousStyle.current = nextDomStyle;
UIManager.updateView(node, domProps);
}
}
};
},
[classList, hostRef, ref, style]
);
}
@@ -12,7 +12,6 @@
import dangerousStyleValue from '../dangerousStyleValue'; import dangerousStyleValue from '../dangerousStyleValue';
import hyphenateStyleName from 'hyphenate-style-name'; import hyphenateStyleName from 'hyphenate-style-name';
import warnValidStyle from '../warnValidStyle';
/** /**
* Sets the value for multiple styles on a node. If a value is specified as * Sets the value for multiple styles on a node. If a value is specified as
@@ -21,18 +20,13 @@ import warnValidStyle from '../warnValidStyle';
* @param {DOMElement} node * @param {DOMElement} node
* @param {object} styles * @param {object} styles
*/ */
function setValueForStyles(node, styles, getStack) { function setValueForStyles(node, styles) {
const style = node.style; const style = node.style;
for (let styleName in styles) { for (let styleName in styles) {
if (!styles.hasOwnProperty(styleName)) { if (!styles.hasOwnProperty(styleName)) {
continue; continue;
} }
const isCustomProperty = styleName.indexOf('--') === 0; const isCustomProperty = styleName.indexOf('--') === 0;
if (process.env.NODE_ENV !== 'production') {
if (!isCustomProperty) {
warnValidStyle(styleName, styles[styleName], getStack);
}
}
const styleValue = dangerousStyleValue(styleName, styles[styleName], isCustomProperty); const styleValue = dangerousStyleValue(styleName, styles[styleName], isCustomProperty);
if (styleName === 'float') { if (styleName === 'float') {
styleName = 'cssFloat'; styleName = 'cssFloat';
+1 -1
View File
@@ -10,7 +10,7 @@ module.exports = {
// resetMocks: true, // resetMocks: true,
rootDir: process.cwd(), rootDir: process.cwd(),
roots: ['<rootDir>/packages'], roots: ['<rootDir>/packages'],
setupFiles: ['jest-canvas-mock'], setupFiles: ['jest-canvas-mock', require.resolve('./setupFiles.js')],
setupFilesAfterEnv: [require.resolve('./setupFramework.js')], setupFilesAfterEnv: [require.resolve('./setupFramework.js')],
snapshotSerializers: ['enzyme-to-json/serializer'], snapshotSerializers: ['enzyme-to-json/serializer'],
testEnvironment: 'jsdom', testEnvironment: 'jsdom',
+10
View File
@@ -0,0 +1,10 @@
/* eslint-env jasmine, jest */
// JSDOM doesn't implement ResizeObserver
class ResizeObserver {
disconnect() {}
observe() {}
unobserve() {}
}
window.ResizeObserver = ResizeObserver;