@axonpack/react-native-devtools-tab 0.1.3 → 0.1.4-canary-dd8fff3e8208f0b71ddbb769703ea0038fcb5c86

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@axonpack/react-native-devtools-tab",
3
- "version": "0.1.3",
3
+ "version": "0.1.4-canary-dd8fff3e8208f0b71ddbb769703ea0038fcb5c86",
4
4
  "description": "Put your own tab in React Native DevTools, with a two-way channel to the running app",
5
5
  "author": "Md Asadujjaman <abappi2019@gmail.com> (https://github.com/abappi19)",
6
6
  "keywords": [
@@ -466,3 +466,29 @@ test("a ref answers the methods React Native calls on a host instance", async ()
466
466
  // Zeroes rather than a refusal, because a layout reading a measurement wants a number.
467
467
  expect(measured).toEqual([0, 0, 0, 0, 0, 0]);
468
468
  });
469
+
470
+ // React moves a keyed node by placing it again: `insertBefore`, or `appendChild` when it goes last.
471
+ // Keeping the old position as well drew one node twice, so both copies updated and were selected
472
+ // together.
473
+ test("a row React moves is moved, not copied, live and in a replay", async () => {
474
+ const { container, sender } = mount();
475
+ const list = (keys: string[]) =>
476
+ createElement(
477
+ "ul",
478
+ null,
479
+ ...keys.map((key) => createElement("li", { key }, key)),
480
+ );
481
+
482
+ sender.render(list(["a", "b", "c"]));
483
+ await settle();
484
+ sender.render(list(["b", "c", "a"]));
485
+ await settle();
486
+ sender.render(list(["c", "a", "b", "d"]));
487
+ await settle();
488
+ expect(container.textContent).toBe("cabd");
489
+
490
+ const second = mount();
491
+ second.receiver.apply(sender.replay());
492
+ await settle();
493
+ expect(second.container.textContent).toBe("cabd");
494
+ });
@@ -101,7 +101,15 @@ export function createRemoteSender(
101
101
  // One reconciler per sender, not one shared. React commits long after `render` returns, when an
102
102
  // effect or a `setState` fires, so a shared one would have to be told which tab it was working for
103
103
  // at a moment nothing is in a position to tell it.
104
+ // React moves a node by placing it again, so a child already here is taken out first. Left in, it
105
+ // stays in the tree twice and a replay draws it twice.
106
+ const detach = (parent: Instance, child: Instance): void => {
107
+ const at = parent.children.indexOf(child);
108
+ if (at >= 0) parent.children.splice(at, 1);
109
+ };
110
+
104
111
  const append = (parent: Instance, child: Instance): void => {
112
+ detach(parent, child);
105
113
  parent.children.push(child);
106
114
  pending.push({ op: "append", parent: parent.id, child: child.id });
107
115
  };
@@ -111,6 +119,7 @@ export function createRemoteSender(
111
119
  child: Instance,
112
120
  before: Instance,
113
121
  ): void => {
122
+ detach(parent, child);
114
123
  const at = parent.children.indexOf(before);
115
124
  parent.children.splice(at < 0 ? parent.children.length : at, 0, child);
116
125
  pending.push({
@@ -89,7 +89,11 @@ export function createRemoteReceiver(): RemoteReceiver {
89
89
  case "append": {
90
90
  const parent = nodes.get(op.parent);
91
91
  const child = nodes.get(op.child);
92
- if (parent && child) parent.children.push(child);
92
+ if (!parent || !child) break;
93
+ // Same as insert: React sends a node it moves to the end as an append.
94
+ const from = parent.children.indexOf(child);
95
+ if (from >= 0) parent.children.splice(from, 1);
96
+ parent.children.push(child);
93
97
  break;
94
98
  }
95
99