@samitouri / QOS-React-2 / commits / 7160f6f584

Fixed owners stack direction and added current element to stack

Brian Vaughn committed May 9, 2019 at 18:11 UTC 7160f6f584d3eb487230fe64b4a76e5086eb7cec
6 files changed +106 -15
src/__tests__/__snapshots__/ownersListContext-test.js.snap
+30 -4
@@ -9,13 +9,17 @@ exports[`OwnersListContext should fetch the owners list for the selected element
9
10 exports[`OwnersListContext should fetch the owners list for the selected element that includes filtered components: owners for "Child" 1`] = `
11 Array [
12 + Object {
13 + "displayName": "Grandparent",
14 + "id": 7,
15 + },
16 Object {
17 "displayName": "Parent",
18 "id": 9,
19 },
20 Object {
17 - "displayName": "Grandparent",
18 - "id": 7,
21 + "displayName": "Child",
22 + "id": 8,
23 },
24 ]
25 `;
@@ -30,13 +34,17 @@ exports[`OwnersListContext should fetch the owners list for the selected element
34
35 exports[`OwnersListContext should fetch the owners list for the selected element: owners for "Child" 1`] = `
36 Array [
37 + Object {
38 + "displayName": "Grandparent",
39 + "id": 2,
40 + },
41 Object {
42 "displayName": "Parent",
43 "id": 3,
44 },
45 Object {
38 - "displayName": "Grandparent",
39 - "id": 2,
46 + "displayName": "Child",
47 + "id": 4,
48 },
49 ]
50 `;
@@ -47,5 +55,23 @@ Array [
55 "displayName": "Grandparent",
56 "id": 2,
57 },
58 + Object {
59 + "displayName": "Parent",
60 + "id": 3,
61 + },
62 +]
63 +`;
64 +
65 +exports[`OwnersListContext should include the current element even if there are no other owners: mount 1`] = `
66 +[root]
67 + <Grandparent>
68 +`;
69 +
70 +exports[`OwnersListContext should include the current element even if there are no other owners: owners for "Grandparent" 1`] = `
71 +Array [
72 + Object {
73 + "displayName": "Grandparent",
74 + "id": 5,
75 + },
76 ]
77 `;
src/__tests__/ownersListContext-test.js
+44
@@ -163,4 +163,48 @@ describe('OwnersListContext', () => {
163
164 done();
165 });
166 +
167 + it('should include the current element even if there are no other owners', async done => {
168 + store.componentFilters = [utils.createDisplayNameFilter('^Parent$')];
169 +
170 + const Grandparent = () => <Parent />;
171 + const Parent = () => null;
172 +
173 + utils.act(() =>
174 + ReactDOM.render(<Grandparent />, document.createElement('div'))
175 + );
176 +
177 + expect(store).toMatchSnapshot('mount');
178 +
179 + const grandparent = ((store.getElementAtIndex(0): any): Element);
180 +
181 + let didFinish = false;
182 +
183 + function Suspender({ owner }) {
184 + const read = React.useContext(OwnersListContext);
185 + const owners = read(owner.id);
186 + expect(owners).toMatchSnapshot(
187 + `owners for "${(owner && owner.displayName) || ''}"`
188 + );
189 + didFinish = true;
190 + return null;
191 + }
192 +
193 + await utils.actSuspense(
194 + () =>
195 + TestRenderer.create(
196 + <Contexts defaultOwnerID={grandparent.id}>
197 + <React.Suspense fallback={null}>
198 + <Suspender owner={grandparent} />
199 + </React.Suspense>
200 + </Contexts>
201 + ),
202 + 3
203 + );
204 + expect(didFinish).toBe(true);
205 +
206 + done();
207 + });
208 +
209 + // TODO (owners) Verify that if an Element in the list is unmounted the stack is updated.
210 });
src/backend/renderer.js
+23 -4
@@ -1696,12 +1696,17 @@ export function attach(
1696
1697 const { _debugOwner } = fiber;
1698
1699 - let owners = null;
1699 + const owners = [
1700 + {
1701 + displayName: getDisplayNameForFiber(fiber) || 'Unknown',
1702 + id,
1703 + },
1704 + ];
1705 +
1706 if (_debugOwner) {
1701 - owners = [];
1707 let owner = _debugOwner;
1708 while (owner !== null) {
1704 - owners.push({
1709 + owners.unshift({
1710 displayName: getDisplayNameForFiber(owner) || 'Unknown',
1711 id: getFiberID(getPrimaryFiber(owner)),
1712 });
@@ -1719,6 +1724,7 @@ export function attach(
1724 }
1725
1726 const {
1727 + _debugOwner,
1728 _debugSource,
1729 stateNode,
1730 memoizedProps,
@@ -1790,6 +1796,19 @@ export function attach(
1796 context = { value: context };
1797 }
1798
1799 + let owners = null;
1800 + if (_debugOwner) {
1801 + owners = [];
1802 + let owner = _debugOwner;
1803 + while (owner !== null) {
1804 + owners.push({
1805 + displayName: getDisplayNameForFiber(owner) || 'Unknown',
1806 + id: getFiberID(getPrimaryFiber(owner)),
1807 + });
1808 + owner = owner._debugOwner || null;
1809 + }
1810 + }
1811 +
1812 const isTimedOutSuspense =
1813 tag === SuspenseComponent && memoizedState !== null;
1814
@@ -1825,7 +1844,7 @@ export function attach(
1844 state: usesHooks ? null : memoizedState,
1845
1846 // List of owners
1828 - owners: getOwnersList(id),
1847 + owners,
1848
1849 // Location of component in source coude.
1850 source: _debugSource,
src/devtools/views/Components/OwnersStack.js
+7 -5
@@ -45,7 +45,7 @@ type State = {|
45 function dialogReducer(state, action) {
46 switch (action.type) {
47 case 'UPDATE_OWNER_ID':
48 - const selectedIndex = state.owners.findIndex(
48 + const selectedIndex = action.owners.findIndex(
49 owner => owner.id === action.ownerID
50 );
51 return {
@@ -71,10 +71,11 @@ export default function OwnerStack() {
71 const [state, dispatch] = useReducer<State, Action>(dialogReducer, {
72 ownerID: null,
73 owners: [],
74 - selectedIndex: -1,
74 + selectedIndex: 0,
75 });
76
77 - // TODO (owners) Explain this and use reducer with ownerID too to avoid inf. loop
77 + // When an owner is selected, we either need to update the selected index, or we need to fetch a new list of owners.
78 + // We use a reducer here so that we can avoid fetching a new list unless the owner ID has actually changed.
79 if (ownerID === null) {
80 dispatch({
81 type: 'UPDATE_OWNER_ID',
@@ -82,11 +83,12 @@ export default function OwnerStack() {
83 owners: [],
84 });
85 } else if (ownerID !== state.ownerID) {
85 - const isInList = state.owners.findIndex(owner => owner.id === ownerID) >= 0;
86 + const isInStore =
87 + state.owners.findIndex(owner => owner.id === ownerID) >= 0;
88 dispatch({
89 type: 'UPDATE_OWNER_ID',
90 ownerID,
89 - owners: isInList ? state.owners : read(ownerID) || [],
91 + owners: isInStore ? state.owners : read(ownerID) || [],
92 });
93 }
94
src/devtools/views/Components/SelectedElement.js
+1 -1
@@ -304,7 +304,7 @@ function InspectedElementView({
304 {owners.map(owner => (
305 <OwnerView
306 key={owner.id}
307 - displayName={owner.displayName}
307 + displayName={owner.displayName || 'Unknown'}
308 id={owner.id}
309 isInStore={store.containsElement(owner.id)}
310 />
src/devtools/views/Components/types.js
+1 -1
@@ -31,7 +31,7 @@ export type Element = {|
31 |};
32
33 export type Owner = {|
34 - displayName: string,
34 + displayName: string | null,
35 id: number,
36 |};
37