DevTools fix props editing for host components (#20055)
Brian Vaughn committed
Oct 19, 2020 at 15:21 UTC
75726fadfd4ab063390805bf5baab966c8523d2c
2 files changed
+43
-9
packages/react-devtools-shared/src/__tests__/editing-test.js
+27
@@ -28,6 +28,7 @@ describe('editing interface', () => {
28
bridge = global.bridge;
29
store = global.store;
30
store.collapseNodesByDefault = false;
31
+ store.componentFilters = [];
32
33
PropTypes = require('prop-types');
34
React = require('react');
@@ -37,8 +38,10 @@ describe('editing interface', () => {
38
describe('props', () => {
39
let committedClassProps;
40
let committedFunctionProps;
41
+ let inputRef;
42
let classID;
43
let functionID;
44
+ let hostComponentID;
45
46
async function mountTestApp() {
47
class ClassComponent extends React.Component {
@@ -60,6 +63,8 @@ describe('editing interface', () => {
63
return null;
64
}
65
66
+ inputRef = React.createRef(null);
67
+
68
const container = document.createElement('div');
69
await utils.actAsync(() =>
70
ReactDOM.render(
@@ -76,6 +81,7 @@ describe('editing interface', () => {
81
shallow="initial"
82
/>
83
,
84
+ <input ref={inputRef} onChange={jest.fn()} value="initial" />
85
</>,
86
container,
87
),
@@ -83,6 +89,7 @@ describe('editing interface', () => {
89
90
classID = ((store.getElementIDAtIndex(0): any): number);
91
functionID = ((store.getElementIDAtIndex(1): any): number);
92
+ hostComponentID = ((store.getElementIDAtIndex(2): any): number);
93
94
expect(committedClassProps).toStrictEqual({
95
array: [1, 2, 3],
@@ -98,6 +105,7 @@ describe('editing interface', () => {
105
},
106
shallow: 'initial',
107
});
108
+ expect(inputRef.current.value).toBe('initial');
109
}
110
111
it('should have editable values', async () => {
@@ -380,6 +388,25 @@ describe('editing interface', () => {
388
object: {},
389
});
390
});
391
+
392
+ it('should support editing host component values', async () => {
393
+ await mountTestApp();
394
+
395
+ function overrideProps(id, path, value) {
396
+ const rendererID = utils.getRendererID();
397
+ bridge.send('overrideValueAtPath', {
398
+ id,
399
+ path,
400
+ rendererID,
401
+ type: 'props',
402
+ value,
403
+ });
404
+ flushPendingUpdates();
405
+ }
406
+
407
+ overrideProps(hostComponentID, ['value'], 'updated');
408
+ expect(inputRef.current.value).toBe('updated');
409
+ });
410
});
411
412
describe('state', () => {
packages/react-devtools-shared/src/backend/renderer.js
+16
-9
@@ -2888,18 +2888,25 @@ export function attach(
2888
}
2889
break;
2890
case 'props':
2891
- if (instance === null) {
2892
- if (typeof overrideProps === 'function') {
2893
- overrideProps(fiber, path, value);
2894
- }
2895
- } else {
2896
- fiber.pendingProps = copyWithSet(instance.props, path, value);
2897
- instance.forceUpdate();
2891
+ switch (fiber.tag) {
2892
+ case ClassComponent:
2893
+ fiber.pendingProps = copyWithSet(instance.props, path, value);
2894
+ instance.forceUpdate();
2895
+ break;
2896
+ default:
2897
+ if (typeof overrideProps === 'function') {
2898
+ overrideProps(fiber, path, value);
2899
+ }
2900
+ break;
2901
}
2902
break;
2903
case 'state':
2901
- setInObject(instance.state, path, value);
2902
- instance.forceUpdate();
2904
+ switch (fiber.tag) {
2905
+ case ClassComponent:
2906
+ setInObject(instance.state, path, value);
2907
+ instance.forceUpdate();
2908
+ break;
2909
+ }
2910
break;
2911
}
2912
}