Skip to content

Commit 171305f

Browse files
committed
Merge pull request #5823 from mgmcdermott/master
Warn when value and defaultValue props are both specified on input or textarea.
2 parents f7850dd + f2b62e9 commit 171305f

File tree

6 files changed

+126
-0
lines changed

6 files changed

+126
-0
lines changed

src/renderers/dom/client/wrappers/ReactDOMInput.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ var instancesByReactID = {};
2525
var didWarnValueLink = false;
2626
var didWarnCheckedLink = false;
2727
var didWarnValueNull = false;
28+
var didWarnValueDefaultValue = false;
29+
var didWarnCheckedDefaultChecked = false;
2830

2931
function forceUpdateIfMounted() {
3032
if (this._rootNodeID) {
@@ -104,6 +106,28 @@ var ReactDOMInput = {
104106
);
105107
didWarnCheckedLink = true;
106108
}
109+
if (props.checked !== undefined && props.defaultChecked !== undefined &&
110+
!didWarnCheckedDefaultChecked) {
111+
warning(
112+
false,
113+
'Input elements must be either controlled or uncontrolled (specify either the ' +
114+
'checked prop, or the defaultChecked prop, but not both). Decide between using a ' +
115+
'controlled or uncontrolled input and remove one of these props. More info: ' +
116+
'https://fb.me/react-controlled-components'
117+
);
118+
didWarnCheckedDefaultChecked = true;
119+
}
120+
if (props.value !== undefined && props.defaultValue !== undefined &&
121+
!didWarnValueDefaultValue) {
122+
warning(
123+
false,
124+
'Input elements must be either controlled or uncontrolled (specify either the value ' +
125+
'prop, or the defaultValue prop, but not both). Decide between using a controlled ' +
126+
'or uncontrolled input and remove one of these props. More info: ' +
127+
'https://fb.me/react-controlled-components'
128+
);
129+
didWarnValueDefaultValue = true;
130+
}
107131
warnIfValueIsNull(props);
108132
}
109133

src/renderers/dom/client/wrappers/ReactDOMSelect.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ var warning = require('warning');
2020

2121
var didWarnValueLink = false;
2222
var didWarnValueNull = false;
23+
var didWarnValueDefaultValue = false;
2324

2425
function updateOptionsIfPendingUpdateAndMounted() {
2526
if (this._rootNodeID && this._wrapperState.pendingUpdate) {
@@ -178,6 +179,18 @@ var ReactDOMSelect = {
178179
onChange: _handleChange.bind(inst),
179180
wasMultiple: Boolean(props.multiple),
180181
};
182+
183+
if (props.value !== undefined && props.defaultValue !== undefined &&
184+
!didWarnValueDefaultValue) {
185+
warning(
186+
false,
187+
'Select elements must be either controlled or uncontrolled (specify either the ' +
188+
'value prop, or the defaultValue prop, but not both). Decide between using a ' +
189+
'controlled or uncontrolled select element and remove one of these props. More info: ' +
190+
'https://fb.me/react-controlled-components'
191+
);
192+
didWarnValueDefaultValue = true;
193+
}
181194
},
182195

183196
getSelectValueContext: function(inst) {

src/renderers/dom/client/wrappers/ReactDOMTextarea.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ var warning = require('warning');
2222

2323
var didWarnValueLink = false;
2424
var didWarnValueNull = false;
25+
var didWarnValDefaultVal = false;
2526

2627
function forceUpdateIfMounted() {
2728
if (this._rootNodeID) {
@@ -91,6 +92,16 @@ var ReactDOMTextarea = {
9192
);
9293
didWarnValueLink = true;
9394
}
95+
if (props.value !== undefined && props.defaultValue !== undefined && !didWarnValDefaultVal) {
96+
warning(
97+
false,
98+
'Textarea elements must be either controlled or uncontrolled (specify either the value ' +
99+
'prop, or the defaultValue prop, but not both). Decide between using a controlled or ' +
100+
'uncontrolled input and remove one of these props. More info: ' +
101+
'https://fb.me/react-controlled-components'
102+
);
103+
didWarnValDefaultVal = true;
104+
}
94105
warnIfValueIsNull(props);
95106
}
96107

src/renderers/dom/client/wrappers/__tests__/ReactDOMInput-test.js

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,40 @@ describe('ReactDOMInput', function() {
415415
expect(console.error.argsForCall.length).toBe(1);
416416
});
417417

418+
it('should throw warning message if checked and defaultChecked props are specified', function() {
419+
ReactTestUtils.renderIntoDocument(
420+
<input type="radio" checked={true} defaultChecked={true} readOnly={true} />
421+
);
422+
expect(console.error.argsForCall[0][0]).toContain(
423+
'Input elements must be either controlled or uncontrolled (specify either the ' +
424+
'checked prop, or the defaultChecked prop, but not both). Decide between using a ' +
425+
'controlled or uncontrolled input and remove one of these props. More info: ' +
426+
'https://fb.me/react-controlled-components'
427+
);
428+
429+
ReactTestUtils.renderIntoDocument(
430+
<input type="radio" checked={true} defaultChecked={true} readOnly={true} />
431+
);
432+
expect(console.error.argsForCall.length).toBe(1);
433+
});
434+
435+
it('should throw warning message if value and defaultValue props are specified', function() {
436+
ReactTestUtils.renderIntoDocument(
437+
<input type="text" value="foo" defaultValue="bar" readOnly={true} />
438+
);
439+
expect(console.error.argsForCall[0][0]).toContain(
440+
'Input elements must be either controlled or uncontrolled (specify either the value ' +
441+
'prop, or the defaultValue prop, but not both). Decide between using a controlled or ' +
442+
'uncontrolled input and remove one of these props. More info: ' +
443+
'https://fb.me/react-controlled-components'
444+
);
445+
446+
ReactTestUtils.renderIntoDocument(
447+
<input type="text" value="foo" defaultValue="bar" readOnly={true} />
448+
);
449+
expect(console.error.argsForCall.length).toBe(1);
450+
});
451+
418452
it('sets type before value always', function() {
419453
var log = [];
420454
var originalCreateElement = document.createElement;

src/renderers/dom/client/wrappers/__tests__/ReactDOMSelect-test.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -490,4 +490,30 @@ describe('ReactDOMSelect', function() {
490490

491491
expect(node.value).toBe('giraffe');
492492
});
493+
494+
it('should throw warning message if value and defaultValue props are specified', function() {
495+
spyOn(console, 'error');
496+
ReactTestUtils.renderIntoDocument(
497+
<select value="giraffe" defaultValue="giraffe" readOnly={true}>
498+
<option value="monkey">A monkey!</option>
499+
<option value="giraffe">A giraffe!</option>
500+
<option value="gorilla">A gorilla!</option>
501+
</select>
502+
);
503+
expect(console.error.argsForCall[0][0]).toContain(
504+
'Select elements must be either controlled or uncontrolled (specify either the ' +
505+
'value prop, or the defaultValue prop, but not both). Decide between using a ' +
506+
'controlled or uncontrolled select element and remove one of these props. More info: ' +
507+
'https://fb.me/react-controlled-components'
508+
);
509+
510+
ReactTestUtils.renderIntoDocument(
511+
<select value="giraffe" defaultValue="giraffe" readOnly={true}>
512+
<option value="monkey">A monkey!</option>
513+
<option value="giraffe">A giraffe!</option>
514+
<option value="gorilla">A gorilla!</option>
515+
</select>
516+
);
517+
expect(console.error.argsForCall.length).toBe(1);
518+
});
493519
});

src/renderers/dom/client/wrappers/__tests__/ReactDOMTextarea-test.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,4 +278,22 @@ describe('ReactDOMTextarea', function() {
278278
ReactTestUtils.renderIntoDocument(<textarea value={null} />);
279279
expect(console.error.argsForCall.length).toBe(1);
280280
});
281+
282+
it('should throw warning message if value and defaultValue are specified', function() {
283+
spyOn(console, 'error');
284+
ReactTestUtils.renderIntoDocument(
285+
<textarea value="foo" defaultValue="bar" readOnly={true} />
286+
);
287+
expect(console.error.argsForCall[0][0]).toContain(
288+
'Textarea elements must be either controlled or uncontrolled (specify either the value ' +
289+
'prop, or the defaultValue prop, but not both). Decide between using a controlled or ' +
290+
'uncontrolled input and remove one of these props. More info: ' +
291+
'https://fb.me/react-controlled-components'
292+
);
293+
294+
ReactTestUtils.renderIntoDocument(
295+
<textarea value="foo" defaultValue="bar" readOnly={true} />
296+
);
297+
expect(console.error.argsForCall.length).toBe(1);
298+
});
281299
});

0 commit comments

Comments
 (0)