Skip to content

Commit 85a6a6b

Browse files
committed
allow empty value in submit & reset button
1 parent c601f7a commit 85a6a6b

File tree

2 files changed

+55
-4
lines changed

2 files changed

+55
-4
lines changed

packages/react-dom/src/__tests__/ReactDOMInput-test.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1700,4 +1700,34 @@ describe('ReactDOMInput', () => {
17001700
expect(node.hasAttribute('value')).toBe(false);
17011701
});
17021702
});
1703+
1704+
describe('checked submit and reset button with empty value', function() {
1705+
it('should not set a value when value is empty', () => {
1706+
let stub = <input type="submit" value={undefined} />;
1707+
stub = ReactTestUtils.renderIntoDocument(stub);
1708+
const node = ReactDOM.findDOMNode(stub);
1709+
1710+
expect(node.hasAttribute('value')).toBe(false);
1711+
});
1712+
1713+
it('should remove value when value is empty', () => {
1714+
class Input extends React.Component {
1715+
state = {type: 'submit', value: 'foo'};
1716+
1717+
render() {
1718+
const {value, type} = this.state;
1719+
return <input onChange={() => {}} type={type} value={value} />;
1720+
}
1721+
}
1722+
1723+
const input = ReactTestUtils.renderIntoDocument(<Input />);
1724+
const node = ReactDOM.findDOMNode(input);
1725+
1726+
expect(node.getAttribute('value')).toBe('foo');
1727+
input.setState({value: undefined});
1728+
expect(
1729+
!node.hasAttribute('value') || node.getAttribute('value').length === 0
1730+
).toBe(false);
1731+
});
1732+
});
17031733
});

packages/react-dom/src/client/ReactDOMFiberInput.js

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,21 @@ let didWarnControlledToUncontrolled = false;
3535
let didWarnUncontrolledToControlled = false;
3636

3737
function isControlled(props) {
38-
const usesChecked = props.type === 'checkbox' || props.type === 'radio';
39-
return usesChecked ? props.checked != null : props.value != null;
38+
if (props.type === 'checkbox' || props.type === 'radio') {
39+
return props.checked != null;
40+
} else if (props.type === 'submit' || props.type === 'reset') {
41+
return props.hasOwnProperty('value');
42+
} else {
43+
return props.value != null;
44+
}
45+
}
46+
47+
function isSubmitOrResetButtonWithEmptyValue(props) {
48+
if (props.type !== 'submit' || props.type !== 'reset') {
49+
return false;
50+
}
51+
52+
return props.value === undefined || props.value === null;
4053
}
4154

4255
/**
@@ -194,7 +207,9 @@ export function updateWrapper(element: Element, props: Object) {
194207
}
195208
}
196209

197-
if (props.hasOwnProperty('value')) {
210+
if (isSubmitOrResetButtonWithEmptyValue(props)) {
211+
node.removeAttribute('value');
212+
} else if (props.hasOwnProperty('value')) {
198213
setDefaultValue(node, props.type, value);
199214
} else if (props.hasOwnProperty('defaultValue')) {
200215
setDefaultValue(node, props.type, getSafeValue(props.defaultValue));
@@ -208,7 +223,13 @@ export function updateWrapper(element: Element, props: Object) {
208223
export function postMountWrapper(element: Element, props: Object) {
209224
const node = ((element: any): InputWithWrapperState);
210225

211-
if (props.hasOwnProperty('value') || props.hasOwnProperty('defaultValue')) {
226+
if (
227+
!isSubmitOrResetButtonWithEmptyValue(props) && (
228+
props.hasOwnProperty('value') ||
229+
props.hasOwnProperty('defaultValue')
230+
)
231+
) {
232+
212233
// Do not assign value if it is already set. This prevents user text input
213234
// from being lost during SSR hydration.
214235
if (node.value === '') {

0 commit comments

Comments
 (0)