๊ธฐ๋ฅ ์ ์์ฒญํ๊ฑฐ๋ ๋ฒ๊ทธ๋ฅผ๋ณด๊ณ ํ์๊ฒ ์ต๋๊น?
๊ณค์ถฉ!
ํ์ฌ ํ๋์ ๋ฌด์์ ๋๊น?
onClick
๋ฐ onChange
ํธ๋ค๋ฌ๋ฅผ ์ฌ์ฉํ์ฌ checkbox
์ ํ์ input
์์๋ฅผ ๋ ๋๋ง ํ ๋ event.preventDefault()
์๋ ๋ถ๊ตฌํ๊ณ onChange
๋ ์ฌ์ ํ ํธ์ถ๋ฉ๋๋ค. event.preventDefault()
๋ onClick
ํธ๋ค๋ฌ์์ ํธ์ถ๋ฉ๋๋ค.
ํ์ฌ ๋์์ด ๋ฒ๊ทธ ์ธ ๊ฒฝ์ฐ ์ฌํ ๋จ๊ณ๋ฅผ ์ ๊ณตํ๊ณ ๊ฐ๋ฅํ๋ฉด https://jsfiddle.net ๋๋ ์ด์ ์ ์ฌํ ๋ฐฉ์ (ํ ํ๋ฆฟ : https://jsfiddle.net/reactjs/69z2wepo/)์ ํตํด ๋ฌธ์ ์ ๋ํ ์ต์ ๋ฐ๋ชจ๋ฅผ ์ ๊ณตํ์ญ์์ค.
์์๋๋ ๋์์ ๋ฌด์์ ๋๊น?
onClick
์ฒ๋ฆฌ๊ธฐ์์ event.preventDefault
๋ฅผ ํธ์ถํ๋ฉด input
์์์ ๊ฐ์ ์
๋ฐ์ดํธํ๋ ๊ธฐ๋ณธ ์์
์ด ๋ฐ์ํ์ง ์๋๋ก (๋๋ ๊ทธ ํจ๊ณผ๋ฅผ ์ทจ์) ๋ฐฉ์งํด์ผํฉ๋๋ค. ์ด๋ ๊ฒํ๋ฉด change
์ด๋ฒคํธ ๋ฆฌ์ค๋๊ฐ ํธ์ถ๋์ง ์์ต๋๋ค. ์์๋๋ ๋์์ https://jsfiddle.net/L1eskzsq/ ๋ฅผ ์ฐธ์กฐ
์ด๋ค ๋ฒ์ ์ React์ ์ด๋ค ๋ธ๋ผ์ฐ์ / OS๊ฐ์ด ๋ฌธ์ ์ ์ํฅ์ ๋ฐ์ต๋๊น?
๋ง์คํฐ, macOS 10.12.2์ ๋น๋๋ฅผ ์ฌ์ฉํ์ฌ ํ ์คํธ๋์์ผ๋ฉฐ ๋ค์์์ ํ์ธ๋์์ต๋๋ค.
Safari 10.0.2๋ ๋ ๊ฒฝ์ฐ ๋ชจ๋ change
์ด๋ฒคํธ ๋ฆฌ์ค๋๋ฅผ ํธ์ถํฉ๋๋ค.
change
์ด๋ฒคํธ์ ์ํด ์์ฑ๋๋ ChangeEventPlugin
์ ๋ํ ์๋ต์ผ๋ก topChange
, ๋น์ ์ ์์ onClick
ํธ๋ค๋ฌ๋ (๋ผ๊ณ ๊ทธ๋์ ์ ์ preventDefault
call), ์ฌ๊ธฐ : https://github.com/facebook/react/blob/master/src/renderers/dom/shared/eventPlugins/ChangeEventPlugin.js#L338
์ด ํ๋ฌ๊ทธ์ธ์ ์ฒดํฌ ๋ฐ์ค์ ๊ฐ์ด ๋ณ๊ฒฝ๋๋์ง ํ์ธํ๋ ค๊ณ ์๋ํ๋ฉฐ, ๊ทธ๋ ๋ค๋ฉด change
์ด๋ฒคํธ๋ฅผ ํ์ ๋ฃ์ต๋๋ค. inputValueTracking
๊ธฐ๋ฅ์ ์ฌ์ฉํ์ฌ ์ด์ ๊ฐ๊ณผ ๋ค์ ๊ฐ์ ๋น๊ตํ์ฌ์ด ๊ฒฐ์ ์ ๋ด๋ฆฝ๋๋ค. ์ฌ๊ธฐ์์ https://github.com/facebook/react/blob/master/src/renderers/dom/shared/ inputValueTracking.js # L154
nextValue
๋ ๋ค์๊ณผ ๊ฐ์ด DOM์์ ์ง์ ๊ฐ์ ธ์ต๋๋ค. value = isCheckable(node) ? '' + node.checked : node.value;
https://github.com/facebook/react/blob/master/src/renderers/dom/shared/inputValueTracking.js# L56
๋ฌธ์ ๋ node.checked
๊ฐ์ด์ด ์์ ์์ ์ผ์์ ์ผ๋ก true์ด๋ฏ๋ก ์ฒซ ๋ฒ์งธ ํด๋ฆญ ํ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
lastValue == false
(์ ํํจ)
nextValue == true
(์๋ชป๋จ)
๋ค์ ํ์ธ๋์ ํด๋ฆญํ๋ฉด ๊ฐ์ด ๋ค์๊ณผ ๊ฐ๊ธฐ ๋๋ฌธ์ change
์ด๋ฒคํธ๊ฐ ๋ ์ด์ ๋ฐ์ํ์ง ์์ต๋๋ค.
lastValue == true
(์๋ชป๋จ)
nextValue == true
(์๋ชป๋จ)
์ ๋ฐ์ ์ผ๋ก ๋ฌธ์ ๋ React๊ฐ onClick
์ preventDefault๊ฐ ํธ์ถ๋๊ธฐ ์ ์ ๋
ธ๋์ checked
๊ฐ์ด ๋ฌด์์ธ์ง DOM์ ์์ฒญํ๋ ๊ฒ ๊ฐ์ต๋๋ค.
์ด ๋ฌธ์ ๋ฅผ ํํค์น๋ ๋ฐ ๋์์ ์ฃผ์ @karelskopek ๋ฐ @Mintaffee ์๊ฒ ๊ฐ์ฌ๋๋ฆฝ๋๋ค.
@aweary ์ด๊ฒ์ด ํด๊ฒฐํ ๊ฐ์น๊ฐ ์๋ค๊ณ ์๊ฐํ์ญ๋๊น?
์ด๊ฑด ์ง์ ์ด ์๋์? React v16.2๋ฅผ ์ฌ์ฉํ๊ณ ์์ผ๋ฉฐ ๋์์ ๋์ผํฉ๋๋ค. onChange๊ฐ ์ฒ์์ผ๋ก ํธ๋ฆฌ๊ฑฐ๋๊ณ ํ์ ํด๋ฆญ์ด ํธ๋ฆฌ๊ฑฐ๋์ง ์์ต๋๋ค. ์ฌ๊ธฐ์ ์ฐ์ ์์๊ฐ ๋์ ์ด์๋ผ๊ณ ํ๊ฒ ์ต๋๋ค ..
๊ด๋ จ์ด ์์ต๋๊น? preventDefault
์ฒดํฌ ๋ฐ์ค onChange
์์ ํธ์ถ๋๋ฉด React์ ๋ธ๋ผ์ฐ์ ์ํ๊ฐ ๋๊ธฐํ๋์ง ์์ต๋๋ค : https://codesandbox.io/s/0qpr936xkv
React 16.8.6์์ ์ฌ์ ํ ๋ฌธ์ ์
๋๋ค. ํ ๊ฐ์ง ๊ฐ๋ฅํ ํด๊ฒฐ ๋ฐฉ๋ฒ์ onClick
ํธ๋ค๋ฌ์์ ๋ชจ๋ ์์
์ ์ํํ๋ ๊ฒ์
๋๋ค.
const radios = ['one', 'two', 'three'];
class Row extends Component {
constructor(props) {
super(props);
this.onClick = this.onClick.bind(this);
this.onChange = this.onChange.bind(this);
}
render() {
const { value } = this.props;
return (
<div className="row">
<div className="radio-group">
{radios.map(radio => (
<label key={radio} className="radio">
<input
type="radio"
name="radio"
value={radio}
checked={radio === value}
onClick={this.onClick}
onChange={this.onChange}
/><span>Radio</span>
</label>
))}
</div>
</div>
);
}
onClick(event) {
// Check something to prevent radio change
if (...) {
event.preventDefault();
return;
}
// Sync value in the store
this.props.setValue(event.target.value);
}
onChange() {
// We need this empty handler to suppress React warning:
// "You provided a `checked` prop to a form field without an `onChange` handler.
// This will render a read-only field. If the field should be mutable use `defaultChecked`.
// Otherwise, set either `onChange` or `readOnly`"
}
}
์ ์ด ๋ ๊ตฌ์ฑ ์์ ๋ฅผ ์ฌ์ฉ
onChange(event) {
// Check something to prevent radio change
if (...) {
return;
}
// Sync value in the store
this.props.setDateTime(event.target.value);
}
๋ ๊ฐ๋จํ ์๋ฃจ์ ์ ์ํด onMouseDown ์ด๋ฒคํธ์์ e.preventDefault๋ฅผ ์ํํ์ฌ onChange๊ฐ ์คํ๋์ง ์๋๋ก ํ ์ ์์ต๋๋ค.
onMouseDown(e) {
if (...) {
e.preventDefault();
return;
}
}
๊ฐ์ฅ ์ ์ฉํ ๋๊ธ
๊ด๋ จ์ด ์์ต๋๊น?
preventDefault
์ฒดํฌ ๋ฐ์คonChange
์์ ํธ์ถ๋๋ฉด React์ ๋ธ๋ผ์ฐ์ ์ํ๊ฐ ๋๊ธฐํ๋์ง ์์ต๋๋ค : https://codesandbox.io/s/0qpr936xkv