Fixed ReactNativeFiber event handling regression (#8959)

* Fixed ReactNativeFiber event system regression introduced in b354db2
Also added test coverage to ReactNativeEvents-test for Fiber

* ReactNative tests now run against fiber renderer when env flag set
Updated the test-framework-setup file so that record-tests runs native tests against ReactNativeFiber. ReactComponentTreeHook native tests all now fail but that's expected.

* Avoid calling setChildren() if no children
This commit is contained in:
Brian Vaughn
2017-02-08 21:28:56 -10:00
committed by GitHub
parent 81bd138144
commit ab757e905c
7 changed files with 77 additions and 59 deletions
@@ -61,6 +61,55 @@ src/renderers/__tests__/ReactComponentTreeHook-test.js
* registers inlined text nodes
* works
src/renderers/__tests__/ReactComponentTreeHook-test.native.js
* uses displayName or Unknown for classic components
* uses displayName, name, or ReactComponent for modern components
* uses displayName, name, or Object for factory components
* uses displayName, name, or StatelessComponent for functional components
* reports a host tree correctly
* reports a simple tree with composites correctly
* reports a tree with composites correctly
* ignores null children
* ignores false children
* reports text nodes as children
* reports a single text node as a child
* reports a single number node as a child
* reports a zero as a child
* skips empty nodes for multiple children
* updates text of a single text child
* updates from no children to a single text child
* updates from a single text child to no children
* updates from no children to multiple text children
* updates from multiple text children to no children
* updates from one text child to multiple text children
* updates from multiple text children to one text child
* updates text nodes when reordering
* updates host nodes when reordering with keys
* updates host nodes when reordering with keys
* updates a single composite child of a different type
* updates a single composite child of the same type
* updates from no children to a single composite child
* updates from a single composite child to no children
* updates mixed children
* updates with a host child
* updates from null to a host child
* updates from a host child to null
* updates from a host child to a composite child
* updates from a composite child to a host child
* updates from null to a composite child
* updates from a composite child to null
* updates with a host child
* updates from null to a host child
* updates from a host child to null
* updates from a host child to a composite child
* updates from a composite child to a host child
* updates from null to a composite child
* updates from a composite child to null
* tracks owner correctly
* purges unmounted components automatically
* reports update counts
* does not report top-level wrapper as a root
src/renderers/__tests__/ReactCompositeComponent-test.js
* should warn about `forceUpdate` on unmounted components
* should warn about `setState` on unmounted components
-49
View File
@@ -558,55 +558,6 @@ src/renderers/__tests__/ReactComponentTreeHook-test.js
* is created during mounting
* is created when calling renderToString during render
src/renderers/__tests__/ReactComponentTreeHook-test.native.js
* uses displayName or Unknown for classic components
* uses displayName, name, or ReactComponent for modern components
* uses displayName, name, or Object for factory components
* uses displayName, name, or StatelessComponent for functional components
* reports a host tree correctly
* reports a simple tree with composites correctly
* reports a tree with composites correctly
* ignores null children
* ignores false children
* reports text nodes as children
* reports a single text node as a child
* reports a single number node as a child
* reports a zero as a child
* skips empty nodes for multiple children
* updates text of a single text child
* updates from no children to a single text child
* updates from a single text child to no children
* updates from no children to multiple text children
* updates from multiple text children to no children
* updates from one text child to multiple text children
* updates from multiple text children to one text child
* updates text nodes when reordering
* updates host nodes when reordering with keys
* updates host nodes when reordering with keys
* updates a single composite child of a different type
* updates a single composite child of the same type
* updates from no children to a single composite child
* updates from a single composite child to no children
* updates mixed children
* updates with a host child
* updates from null to a host child
* updates from a host child to null
* updates from a host child to a composite child
* updates from a composite child to a host child
* updates from null to a composite child
* updates from a composite child to null
* updates with a host child
* updates from null to a host child
* updates from a host child to null
* updates from a host child to a composite child
* updates from a composite child to a host child
* updates from null to a composite child
* updates from a composite child to null
* tracks owner correctly
* purges unmounted components automatically
* reports update counts
* does not report top-level wrapper as a root
src/renderers/__tests__/ReactCompositeComponent-test.js
* should support module pattern components
* should support rendering to different child types over time
+7
View File
@@ -3,6 +3,7 @@
// We want to globally mock this but jest doesn't let us do that by default
// for a file that already exists. So we have to explicitly mock it.
jest.mock('ReactDOM');
jest.mock('ReactNative');
jest.mock('ReactDOMFeatureFlags', () => {
const flags = require.requireActual('ReactDOMFeatureFlags');
return Object.assign({}, flags, {
@@ -15,6 +16,12 @@ jest.mock('ReactFeatureFlags', () => {
disableNewFiberFeatures: true,
});
});
jest.mock('ReactNativeFeatureFlags', () => {
const flags = require.requireActual('ReactNativeFeatureFlags');
return Object.assign({}, flags, {
useFiber: flags.useFiber || !!process.env.REACT_DOM_JEST_USE_FIBER,
});
});
// Error logging varies between Fiber and Stack;
// Rather than fork dozens of tests, mock the error-logging file by default.
@@ -66,8 +66,8 @@ function getTagFromInstance(inst) {
return tag;
}
function getFiberEventHandlersFromTag(tag) {
return instanceProps[tag] || null;
function getFiberCurrentPropsFromNode(stateNode) {
return instanceProps[stateNode._nativeTag] || null;
}
function updateFiberProps(tag, props) {
@@ -82,7 +82,7 @@ var ReactNativeComponentTree = {
precacheNode,
uncacheFiberNode,
uncacheNode,
getFiberCurrentPropsFromNode: getFiberEventHandlersFromTag,
getFiberCurrentPropsFromNode,
updateFiberProps,
};
+5
View File
@@ -213,6 +213,11 @@ const NativeRenderer = ReactFiberReconciler({
props : Props,
rootContainerInstance : Container,
) : boolean {
// Don't send a no-op message over the bridge.
if (parentInstance._children.length === 0) {
return false;
}
// Map from child objects to native tags.
// Either way we need to pass a copy of the Array to prevent it from being frozen.
const nativeTags = parentInstance._children.map(
@@ -42,7 +42,6 @@ it('handles events', () => {
uiViewClassName: 'View',
});
var log = [];
ReactNative.render(
<View
@@ -63,7 +62,12 @@ it('handles events', () => {
);
expect(UIManager.createView.mock.calls.length).toBe(2);
var innerTag = UIManager.createView.mock.calls[1][0];
// Don't depend on the order of createView() calls.
// Stack creates views outside-in; fiber creates them inside-out.
var innerTag = UIManager.createView.mock.calls.find(
args => args[3].foo === 'inner'
)[0];
EventEmitter.receiveTouches(
'topTouchStart',
@@ -18,6 +18,8 @@ var UIManager;
describe('ReactNative', () => {
beforeEach(() => {
jest.resetModules();
React = require('React');
ReactNative = require('ReactNative');
UIManager = require('UIManager');
@@ -45,17 +47,17 @@ describe('ReactNative', () => {
ReactNative.render(<View foo="foo" />, 11);
expect(UIManager.createView.mock.calls.length).toBe(2);
expect(UIManager.setChildren.mock.calls.length).toBe(2);
expect(UIManager.createView.mock.calls.length).toBe(1);
expect(UIManager.setChildren.mock.calls.length).toBe(1);
expect(UIManager.manageChildren).not.toBeCalled();
expect(UIManager.updateView).not.toBeCalled();
ReactNative.render(<View foo="bar" />, 11);
expect(UIManager.createView.mock.calls.length).toBe(2);
expect(UIManager.setChildren.mock.calls.length).toBe(2);
expect(UIManager.createView.mock.calls.length).toBe(1);
expect(UIManager.setChildren.mock.calls.length).toBe(1);
expect(UIManager.manageChildren).not.toBeCalled();
expect(UIManager.updateView).toBeCalledWith(3, 'View', { foo: 'bar' });
expect(UIManager.updateView).toBeCalledWith(2, 'View', { foo: 'bar' });
});
it('returns the correct instance and calls it in the callback', () => {