Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Allocate unique reactTags for RN and Fabric #12587

Merged
merged 1 commit into from
Apr 10, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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