Skip to content

Commit

Permalink
Allocate unique reactTags for RN and Fabric (facebook#12587)
Browse files Browse the repository at this point in the history
Took this opportunity to remove some abstract overhead.

In Fabric it is extra simple since they no longer overlap with root tags.
  • Loading branch information
sebmarkbage authored and rhagigi committed Apr 19, 2018
1 parent ce45bf6 commit f91be33
Show file tree
Hide file tree
Showing 6 changed files with 29 additions and 65 deletions.
14 changes: 11 additions & 3 deletions packages/react-native-renderer/src/ReactFabricRenderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import * as ReactNativeAttributePayload from './ReactNativeAttributePayload';
import * as ReactNativeFrameScheduling from './ReactNativeFrameScheduling';
import * as ReactNativeViewConfigRegistry from './ReactNativeViewConfigRegistry';
import ReactFiberReconciler from 'react-reconciler';
import ReactNativeTagHandles from './ReactNativeTagHandles';

import deepFreezeAndThrowOnMutationInDev from 'deepFreezeAndThrowOnMutationInDev';
import emptyObject from 'fbjs/lib/emptyObject';
Expand All @@ -30,6 +29,12 @@ import TextInputState from 'TextInputState';
import FabricUIManager from 'FabricUIManager';
import UIManager from 'UIManager';

// Counter for uniquely identifying views.
// % 10 === 1 means it is a rootTag.
// % 2 === 0 means it is a Fabric tag.
// This means that they never overlap.
let nextReactTag = 2;

/**
* This is used for refs on host components.
*/
Expand Down Expand Up @@ -133,7 +138,9 @@ const ReactFabricRenderer = ReactFiberReconciler({
hostContext: {},
internalInstanceHandle: Object,
): Instance {
const tag = ReactNativeTagHandles.allocateTag();
const tag = nextReactTag;
nextReactTag += 2;

const viewConfig = ReactNativeViewConfigRegistry.get(type);

if (__DEV__) {
Expand Down Expand Up @@ -171,7 +178,8 @@ const ReactFabricRenderer = ReactFiberReconciler({
hostContext: {},
internalInstanceHandle: Object,
): TextInstance {
const tag = ReactNativeTagHandles.allocateTag();
const tag = nextReactTag;
nextReactTag += 2;

const node = FabricUIManager.createNode(
tag, // reactTag
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import {batchedUpdates} from 'events/ReactGenericBatching';
import warning from 'fbjs/lib/warning';

import {getInstanceFromNode} from './ReactNativeComponentTree';
import ReactNativeTagHandles from './ReactNativeTagHandles';

import type {AnyNativeEvent} from 'events/PluginModuleType';

Expand Down Expand Up @@ -166,7 +165,7 @@ export function receiveTouches(
let rootNodeID = null;
const target = nativeEvent.target;
if (target !== null && target !== undefined) {
if (target < ReactNativeTagHandles.tagsStartAt) {
if (target < 1) {
if (__DEV__) {
warning(
false,
Expand Down
18 changes: 15 additions & 3 deletions packages/react-native-renderer/src/ReactNativeFiberRenderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import {
} from './ReactNativeComponentTree';
import ReactNativeFiberHostComponent from './ReactNativeFiberHostComponent';
import * as ReactNativeFrameScheduling from './ReactNativeFrameScheduling';
import ReactNativeTagHandles from './ReactNativeTagHandles';

type Container = number;
export type Instance = {
Expand All @@ -36,6 +35,19 @@ export type Instance = {
type Props = Object;
type TextInstance = number;

// Counter for uniquely identifying views.
// % 10 === 1 means it is a rootTag.
// % 2 === 0 means it is a Fabric tag.
let nextReactTag = 3;
function allocateTag() {
let tag = nextReactTag;
if (tag % 10 === 1) {
tag += 2;
}
nextReactTag = tag + 2;
return tag;
}

function recursivelyUncacheFiberNode(node: Instance | TextInstance) {
if (typeof node === 'number') {
// Leaf node (eg text)
Expand All @@ -62,7 +74,7 @@ const NativeRenderer = ReactFiberReconciler({
hostContext: {},
internalInstanceHandle: Object,
): Instance {
const tag = ReactNativeTagHandles.allocateTag();
const tag = allocateTag();
const viewConfig = ReactNativeViewConfigRegistry.get(type);

if (__DEV__) {
Expand Down Expand Up @@ -101,7 +113,7 @@ const NativeRenderer = ReactFiberReconciler({
hostContext: {},
internalInstanceHandle: Object,
): TextInstance {
const tag = ReactNativeTagHandles.allocateTag();
const tag = allocateTag();

UIManager.createView(
tag, // reactTag
Expand Down
54 changes: 0 additions & 54 deletions packages/react-native-renderer/src/ReactNativeTagHandles.js

This file was deleted.

3 changes: 1 addition & 2 deletions packages/react-native-renderer/src/__mocks__/UIManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@

// Mock of the Native Hooks

const ReactNativeTagHandles = require('../ReactNativeTagHandles').default;
const invariant = require('fbjs/lib/invariant');

// Map of viewTag -> {children: [childTag], parent: ?parentTag}
Expand All @@ -18,7 +17,7 @@ let views = new Map();

function autoCreateRoot(tag) {
// Seriously, this is how we distinguish roots in RN.
if (!views.has(tag) && ReactNativeTagHandles.reactTagIsNativeTopRootID(tag)) {
if (!views.has(tag) && tag % 10 === 1) {
roots.push(tag);
views.set(tag, {
children: [],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ describe('ReactNative', () => {
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(2, 'View', {foo: 'bar'});
expect(UIManager.updateView).toBeCalledWith(3, 'View', {foo: 'bar'});
});

it('should not call UIManager.updateView after render for properties that have not changed', () => {
Expand Down

0 comments on commit f91be33

Please sign in to comment.