Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Warn if input changes controlledness - also for null (#7544) #7603

Merged
merged 1 commit into from
Aug 29, 2016
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
2 changes: 1 addition & 1 deletion src/renderers/dom/client/wrappers/ReactDOMInput.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ function forceUpdateIfMounted() {

function isControlled(props) {
var usesChecked = props.type === 'checkbox' || props.type === 'radio';
return usesChecked ? props.checked !== undefined : props.value !== undefined;
return usesChecked ? props.checked != null : props.value != null;
}

/**
Expand Down
96 changes: 90 additions & 6 deletions src/renderers/dom/client/wrappers/__tests__/ReactDOMInput-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -580,7 +580,7 @@ describe('ReactDOMInput', function() {
expect(console.error.calls.count()).toBe(1);
});

it('should warn if controlled input switches to uncontrolled', function() {
it('should warn if controlled input switches to uncontrolled (value is undefined)', function() {
var stub = <input type="text" value="controlled" onChange={emptyFunction} />;
var container = document.createElement('div');
ReactDOM.render(stub, container);
Expand All @@ -594,6 +594,20 @@ describe('ReactDOMInput', function() {
);
});

it('should warn if controlled input switches to uncontrolled (value is null)', function() {
var stub = <input type="text" value="controlled" onChange={emptyFunction} />;
var container = document.createElement('div');
ReactDOM.render(stub, container);
ReactDOM.render(<input type="text" value={null} />, container);
expect(console.error.calls.count()).toBeGreaterThan(0);
expect(console.error.calls.argsFor(1)[0]).toContain(
'A component is changing a controlled input of type text to be uncontrolled. ' +
'Input elements should not switch from controlled to uncontrolled (or vice versa). ' +
'Decide between using a controlled or uncontrolled input ' +
'element for the lifetime of the component. More info: https://fb.me/react-controlled-components'
);
});

it('should warn if controlled input switches to uncontrolled with defaultValue', function() {
var stub = <input type="text" value="controlled" onChange={emptyFunction} />;
var container = document.createElement('div');
Expand All @@ -608,7 +622,7 @@ describe('ReactDOMInput', function() {
);
});

it('should warn if uncontrolled input switches to controlled', function() {
it('should warn if uncontrolled input (value is undefined) switches to controlled', function() {
var stub = <input type="text" />;
var container = document.createElement('div');
ReactDOM.render(stub, container);
Expand All @@ -622,7 +636,21 @@ describe('ReactDOMInput', function() {
);
});

it('should warn if controlled checkbox switches to uncontrolled', function() {
it('should warn if uncontrolled input (value is null) switches to controlled', function() {
var stub = <input type="text" value={null} />;
var container = document.createElement('div');
ReactDOM.render(stub, container);
ReactDOM.render(<input type="text" value="controlled" />, container);
expect(console.error.calls.count()).toBeGreaterThan(0);
expect(console.error.calls.argsFor(1)[0]).toContain(
'A component is changing an uncontrolled input of type text to be controlled. ' +
'Input elements should not switch from uncontrolled to controlled (or vice versa). ' +
'Decide between using a controlled or uncontrolled input ' +
'element for the lifetime of the component. More info: https://fb.me/react-controlled-components'
);
});

it('should warn if controlled checkbox switches to uncontrolled (checked is undefined)', function() {
var stub = <input type="checkbox" checked={true} onChange={emptyFunction} />;
var container = document.createElement('div');
ReactDOM.render(stub, container);
Expand All @@ -636,6 +664,20 @@ describe('ReactDOMInput', function() {
);
});

it('should warn if controlled checkbox switches to uncontrolled (checked is null)', function() {
var stub = <input type="checkbox" checked={true} onChange={emptyFunction} />;
var container = document.createElement('div');
ReactDOM.render(stub, container);
ReactDOM.render(<input type="checkbox" checked={null} />, container);
expect(console.error.calls.count()).toBe(1);
expect(console.error.calls.argsFor(0)[0]).toContain(
'A component is changing a controlled input of type checkbox to be uncontrolled. ' +
'Input elements should not switch from controlled to uncontrolled (or vice versa). ' +
'Decide between using a controlled or uncontrolled input ' +
'element for the lifetime of the component. More info: https://fb.me/react-controlled-components'
);
});

it('should warn if controlled checkbox switches to uncontrolled with defaultChecked', function() {
var stub = <input type="checkbox" checked={true} onChange={emptyFunction} />;
var container = document.createElement('div');
Expand All @@ -650,7 +692,7 @@ describe('ReactDOMInput', function() {
);
});

it('should warn if uncontrolled checkbox switches to controlled', function() {
it('should warn if uncontrolled checkbox (checked is undefined) switches to controlled', function() {
var stub = <input type="checkbox" />;
var container = document.createElement('div');
ReactDOM.render(stub, container);
Expand All @@ -664,7 +706,21 @@ describe('ReactDOMInput', function() {
);
});

it('should warn if controlled radio switches to uncontrolled', function() {
it('should warn if uncontrolled checkbox (checked is null) switches to controlled', function() {
var stub = <input type="checkbox" checked={null} />;
var container = document.createElement('div');
ReactDOM.render(stub, container);
ReactDOM.render(<input type="checkbox" checked={true} />, container);
expect(console.error.calls.count()).toBe(1);
expect(console.error.calls.argsFor(0)[0]).toContain(
'A component is changing an uncontrolled input of type checkbox to be controlled. ' +
'Input elements should not switch from uncontrolled to controlled (or vice versa). ' +
'Decide between using a controlled or uncontrolled input ' +
'element for the lifetime of the component. More info: https://fb.me/react-controlled-components'
);
});

it('should warn if controlled radio switches to uncontrolled (checked is undefined)', function() {
var stub = <input type="radio" checked={true} onChange={emptyFunction} />;
var container = document.createElement('div');
ReactDOM.render(stub, container);
Expand All @@ -678,6 +734,20 @@ describe('ReactDOMInput', function() {
);
});

it('should warn if controlled radio switches to uncontrolled (checked is null)', function() {
var stub = <input type="radio" checked={true} onChange={emptyFunction} />;
var container = document.createElement('div');
ReactDOM.render(stub, container);
ReactDOM.render(<input type="radio" checked={null} />, container);
expect(console.error.calls.count()).toBe(1);
expect(console.error.calls.argsFor(0)[0]).toContain(
'A component is changing a controlled input of type radio to be uncontrolled. ' +
'Input elements should not switch from controlled to uncontrolled (or vice versa). ' +
'Decide between using a controlled or uncontrolled input ' +
'element for the lifetime of the component. More info: https://fb.me/react-controlled-components'
);
});

it('should warn if controlled radio switches to uncontrolled with defaultChecked', function() {
var stub = <input type="radio" checked={true} onChange={emptyFunction} />;
var container = document.createElement('div');
Expand All @@ -692,7 +762,7 @@ describe('ReactDOMInput', function() {
);
});

it('should warn if uncontrolled radio switches to controlled', function() {
it('should warn if uncontrolled radio (checked is undefined) switches to controlled', function() {
var stub = <input type="radio" />;
var container = document.createElement('div');
ReactDOM.render(stub, container);
Expand All @@ -706,6 +776,20 @@ describe('ReactDOMInput', function() {
);
});

it('should warn if uncontrolled radio (checked is null) switches to controlled', function() {
var stub = <input type="radio" checked={null} />;
var container = document.createElement('div');
ReactDOM.render(stub, container);
ReactDOM.render(<input type="radio" checked={true} />, container);
expect(console.error.calls.count()).toBe(1);
expect(console.error.calls.argsFor(0)[0]).toContain(
'A component is changing an uncontrolled input of type radio to be controlled. ' +
'Input elements should not switch from uncontrolled to controlled (or vice versa). ' +
'Decide between using a controlled or uncontrolled input ' +
'element for the lifetime of the component. More info: https://fb.me/react-controlled-components'
);
});

it('should not warn if radio value changes but never becomes controlled', function() {
var container = document.createElement('div');
ReactDOM.render(<input type="radio" value="value" />, container);
Expand Down