
๐ก๋ ธ๋ง๋์ฝ๋ ๋๊ผฌ์ค์ ๊ฐ์๋ฅผ ๋ณด๋ฉฐ ๊ณต๋ถํ๋ ์๋ฆฌ์ฆ์ ๋๋ค.
unite converter(๋จ์๋ณํ๊ธฐ) ๋ง๋ค๊ธฐ
const root = document.getElementById("root");
const App = () => {
return (
<div>
<h1 class="hi">Super Converter</h1>
<label for="minutes">Minutes</label>
<input type="number" placeholder="Minutes" id="minutes"/>
<label for="hours">Hours</label>
<input type="number" placeholder="Hours" id="hours"/>
</div>
);
};
ReactDOM.render(<App />, root);

์ด๋ ๊ฒ ์์ฑํ๋ ๊ฒ์ด ๋ฌธ์ ์์ด ๋ณด์ด๊ฒ ์ง๋ง react์์๋ ์์ ํ ํ๋ฆฐ ๋ฐฉ์์ด๋ค. ํ์ง๋ง ์ฝ์์์ ์๋ฌ๋ ๋ณด์ฌ์ง์ง ์๋๋ฐ react.production.min.js์ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์ด๋ค.

react.development.js๋ฅผ ์ฌ์ฉํ๊ฒ ๋๋ฉด ์ ํจํ์ง ์์ DOM property 'for'๊ณผ 'class'๊ฐ ์๋ค๋ ์๋ฌ๊ฐ ์ถ๋ ฅ๋๋๋ฐ, ์ด๊ฒ์ด ์ ๋ฌธ์ ๊ฐ ๋๋๋ฉด javascript์์ ์ด๋ฏธ ์ ์ ๋ ์ฉ์ด์ด๊ธฐ ๋๋ฌธ์ด๋ค.

jsx์์ ๋ช๊ฐ์ง ๊ธฐ์ตํด์ผํ๋ ๋ถ๋ถ์ด ์๋๋ฐ, class, for์ ์ฌ์ฉํ ์ ์๋ค๋ ๊ฒ์ด๋ค.
๊ทธ๋ ๋ค๋ฉด jsx์์ class์ for์ ์ด๋ป๊ฒ ํํํด์ผํ ๊น?
const root = document.getElementById("root");
const App = () => {
return (
<div>
<h1 className="hi">Super Converter</h1>
<label htmlFor="minutes">Minutes</label>
<input type="number" placeholder="Minutes" id="minutes" />
<label htmlFor="hours">Hours</label>
<input type="number" placeholder="Hours" id="hours" />
</div>
);
};
ReactDOM.render(<App />, root);
class๋ className์ผ๋ก, for์ htmlFor๋ก ๋์ฒดํด์ ์์ฑํด์ผํ๋ค.
production ๊ณผ development์ ์ฐจ์ด
production์ ๋ฐฐํฌ ๋ชจ๋, development๋ ๊ฐ๋ฐ ๋ชจ๋๋ฅผ ์๋ฏธํ๋ค.
๊ฐ๋ฐ๋ชจ๋๋ ๋ฒ๊ทธ๋ก ์ด์ด์ง ์ ์๋ ์์๋ฅผ ๋ฏธ๋ฆฌ ๊ฒฝ๊ณ ํ๋ ๊ฒ์ฆ ์ฝ๋๊ฐ ํฌํจ๋์ด์์ง๋ง, ๋ฒ๋ค ํฌ๊ธฐ๋ฅผ ์ฆ๊ฐ์์ผ ์ฑ ์๋๋ฅผ ๋๋ฆฌ๊ฒ ํ ์ ์๋ค.
๐๐ป์ฐธ๊ณ : ๊ฐ๋ฐ๋ชจ๋๋ ์ด๋ป๊ฒ ์๋ํ ๊น?
jsx์ด ์น์ํ ์ด์ ๋ ๋ช๊ฐ์ง ์ฐจ์ด๋ฅผ ์ ์ธํ๋ฉด javascript์ ๊ฑฐ์ ๊ฐ๊ธฐ ๋๋ฌธ์ด๋ค.
์ด์ ์ ๊ณต๋ถํ๋ react๋ฌธ๋ฒ๊ณผ js์ jsx์ ์ฝ๊ฐ์ ์ฐจ์ด์ ์ ๊ธฐ์ตํ๋ฉฐ input์ state๋ฅผ onChange์ด๋ฒคํธ๋ก setMinutes๋ฅผ ์คํํ๊ณ ์ ๋ฌ์ธ์ event๋ฅผ ํตํด target์ value๋ฅผ ๊ฐ์ ธ์จ๋ค.
const App = () => {
const [minutes, setMinutes] = React.useState();
const onChange = (event) => {
setMinutes(event.target.value);
};
return (
<div>
<h1 className="hi">Super Converter</h1>
<label htmlFor="minutes">Minutes</label>
<input
type="number"
placeholder="Minutes"
id="minutes"
value={minutes}
onChange={onChange}
/>
<h4>๋๋ ์ด๊ฑธ ์ฐ๊ณ ์ถ์ง? {minutes}</h4>
<label htmlFor="hours">Hours</label>
<input type="number" placeholder="Hours" id="hours" />
</div>
);
};
ReactDOM.render(<App />, root);
๊ทธ๋ฐ๋ฐ ์ด ์ฝ๋๋ฅผ ์คํํ๋ฉด ์๋์ ํ์ง๋ง ๋ค์๊ณผ ๊ฐ์ ์๋ฌ๊ฐ ์ถ๋ ฅ๋๋ค.
react-dom.development.js:73 Warning: A component is changing an uncontrolled input to be controlled. This is likely caused by the value changing from undefined to a defined value, which should not happen. Decide between using a controlled or uncontrolled input element for the lifetime of the component.
๊ฑฐ๋์ ๋ฏธํ๊ณ ๋ณธ๋ก ๋ง ๋งํ๋ค๋ฉด ์ด๊ธฐ๊ฐ์ด ์๊ธฐ ๋๋ฌธ์ ์๊ธด ๋ฌธ์ ๋ผ๋ ๋ป์ด๋ค.
const [minutes, setMinutes] = React.useState(0);
React.useState()์ ์ด๊ธฐ๊ฐ์ ์
๋ ฅํ๊ณ ์คํํ๋ฉด ์๋ฌ์์ด ์๋ํ๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.

minute๋ฅผ hours๋ก ๋ณ๊ฒฝํ๋ ์ฝ๋๋ฅผ ์์ฑํด๋ณธ๋ค.
๊ฐ๋จํ๋ค. minute์ ๋์ผํ value๋ฅผ hours์ ํ ๋นํ๊ณ , value / 60 ์ ์คํํ๋ฉด ๋๋ค.
<div>
<h1 className="hi">Super Converter</h1>
<label htmlFor="minutes">Minutes</label>
<input
type="number"
placeholder="Minutes"
id="minutes"
value={minutes}
onChange={onChange}
/>
<label htmlFor="hours">Hours</label>
<input
type="number"
placeholder="Hours"
id="hours"
value={minutes / 60}
/>
</div>
ํ์ง๋ง ๋ฌธ์ ๊ฐ ๋ฐ์ํ๋ค. ์๋์๋ ๋ฌธ์ ๊ฐ ์์ง๋ง ์ฝ์์ ์๋ฌ๊ฐ ์๊ธด๋ค.
id=hours๊ฐ ์
๋ ฅํ ์ ์๋ input์ธ๋ฐ value๋ minutes์์ ๋ฐ์์จ ๊ฐ์ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์ด๋ค.
์ด๊ฒฝ์ฐ๋ ์ฝ์์์ ์ค hint๋๋ก readOnly๋ฅผ ์ถ๊ฐ๋ก ์
๋ ฅํด์ฃผ๋ฉด ํด๊ฒฐ๋๋ค.
<input
type="number"
placeholder="Hours"
id="hours"
value={minutes / 60}
readOnly
/>
value={minutes / 60}๋ฅผ ์ฌ์ฉํ๋ฉด minutes์ ๊ฐ์ ๋ฐ๋ผ ์์ซ์ ์ผ๋ก ๋จ์ด์ง ์ ์๋ค.
Math.round()๋ฅผ ์ฌ์ฉํ์ฌ ์ฐ์ฐ๊ฒฐ๊ณผ๋ฅผ ๋ฐ์ฌ๋ฆผํ๋ฉฐ ์ ์๋ก ๋ง๋ค์ด์ฃผ๋ฉด ํจ์ฌ ๊น๋ํ๋ค.
๋ชจ๋ ๊ฒ์ ์ด๊ธฐํํ๋ ๋ฒํผ์ ๋ง๋ค์ด๋ณธ๋ค.
const [minutes, setMinutes] = React.useState(0);
const onChange = (event) => {
setMinutes(event.target.value);
};
const reset = () => {
setMinutes(0);
};
return (
<div>
<h1 className="hi">Super Converter</h1>
<div>
<label htmlFor="minutes">Minutes</label>
<input
type="number"
placeholder="Minutes"
id="minutes"
value={minutes}
onChange={onChange}
/>
<label htmlFor="hours">Hours</label>
<input
type="number"
placeholder="Hours"
id="hours"
value={Math.round(minutes / 60)}
readOnly
/>
<button onClick={reset}>์ด๊ธฐํ</button>
</div>
</div>
);
reset์ด๋ผ๋ ํจ์๋ฅผ ๋ด๊ณ ์๋ btn์ ํด๋ฆญํ๋ฉด setMinutes(0)๊ฐ ์คํ๋๊ณ , ์ด๊ธฐ๊ฐ์ธ 0์ผ๋ก state๊ฐ ๋ณ๊ฒฝ๋๋ค.

const [filpped, setFilpped] = React.useState(false);
๊ธฐ๋ณธ๊ฐ์ด false์ธ state๋ฅผ ํ๋ ์์ฑํ๊ณ , ์ด state์ ๋ฐ๋ผ์ filpํ๋ ์ฝ๋๋ฅผ ์์ฑํ๋ค.
const onFilp = () => {
setFilpped((current) => !current);
};
<button onClick={onFilp}>๋ค์ง๊ธฐ</button>
hours์ minutes์ ํ์ฑํ, ๋นํ์ฑํ ์ํ๋ฅผ ๋ฐ๊พธ๊ณ ์๊ฐ์ ๋ถ ๋จ์๋ก, ๋ถ์ ์๊ฐ ๋จ์๋ก ๋ฐ๊พธ๋ ๋ฒํผ๊ณผ ํจ์ onFilp์ ๋ง๋ค์๋ค. onFilp์์ ์คํ๋๋ setFilpped๋ ํจ์ํํ๋ก ๋ง๋ค์ด current๋ผ๋ ์ ๋ฌ์ธ์์ ํ์ฌ์ state๊ฐ์ ์์ ์ ์ผ๋ก ๋ฐ์์ค๊ณ , ํจ์๊ฐ ์คํ๋๋ฉด current์ ๋ฐ๋์ ๊ฐ์ current๋ก stateUpdateํ๋๋ก ํ๋ค.
current๊ฐ false ์ด๋ฉด true, current๊ฐ true์ด๋ฉด false๋ก ๋ฐ๋ณต์ ์ผ๋ก ๋ณ๊ฒฝ๋๋ค.
<div>
<label htmlFor="minutes">Minutes</label>
<input
type="number"
placeholder="Minutes"
id="minutes"
value={minutes}
onChange={onChange}
/>
<label htmlFor="hours">Hours</label>
<input
type="number"
placeholder="Hours"
id="hours"
value={Math.round(minutes / 60)}
onChange={onChange}
disabled
/>
<button onClick={reset}>์ด๊ธฐํ</button>
<button onClick={onFilp}>๋ค์ง๊ธฐ</button>
</div>
input id="minutes"์ input id="hours"์ ํ์ฑ ๋นํ์ฑํ ์ํ๋ฅผ ํ๋์ ๋ณด๊ธฐ ์ฝ๋๋ก readOnly์์ disabled๋ก ๋ณ๊ฒฝํ๋ค.
์ด์ ์ผํญ์ฐ์ฐ์๋ฅผ ํ์ฉํ์ฌ state๋ฅผ upDateํด๋ณธ๋ค.
//์ด๊ธฐ๊ฐ
const [filpped, setFilpped] = React.useState(false);
//์คํ๋๋ ํจ์
const onFilp = () => {
setFilpped((current) => !current);
};
<div>
<h1 className="hi">Super Converter</h1>
<div>
<label htmlFor="minutes">Minutes</label>
<input
type="number"
placeholder="Minutes"
id="minutes"
//filpped๊ฐ true์ด๋ฉด Math.round(minutes * 60) ์คํ. ์๋๋ผ๋ฉด minutes๋ฅผ ๋ณด์ฌ์ค๋ค.
value={filpped ? Math.round(minutes * 60) : minutes}
onChange={onChange}
//filpped๊ฐ true์ผ๋ disabled์ฒ๋ฆฌ๋๋ค.
disabled={filpped}
/>
<label htmlFor="hours">Hours</label>
<input
type="number"
placeholder="Hours"
id="hours"
//filpped๊ฐ true์ด๋ฉด minutes๋ฅผ ๋ณด์ฌ์ฃผ๊ณ , ์๋๋ผ๋ฉด Math.round(minutes * 60) ์คํ.
value={filpped ? minutes : Math.round(minutes / 60)}
onChange={onChange}
//filpped๊ฐ false์ผ๋ disabled์ฒ๋ฆฌ๋๋ค.
disabled={!filpped}
/>
<button onClick={reset}>์ด๊ธฐํ</button>
<button onClick={onFilp}>๋ค์ง๊ธฐ</button>
</div>
</div>

//์ ์ฒด์ฝ๋
const root = document.getElementById("root");
const App = () => {
const [minutes, setMinutes] = React.useState(0);
const [filpped, setFilpped] = React.useState(false);
const onChange = (event) => {
setMinutes(event.target.value);
};
const reset = () => {
setMinutes(0);
};
const onFilp = () => {
setFilpped((current) => !current);
};
return (
<div>
<h1 className="hi">Super Converter</h1>
<div>
<label htmlFor="minutes">Minutes</label>
<input
type="number"
placeholder="Minutes"
id="minutes"
//value={filpped ? minutes * 60 : minutes}
value={filpped ? Math.round(minutes * 60) : minutes}
onChange={onChange}
disabled={filpped}
/>
<label htmlFor="hours">Hours</label>
<input
type="number"
placeholder="Hours"
id="hours"
value={filpped ? minutes : Math.round(minutes / 60)}
onChange={onChange}
disabled={!filpped}
/>
<button onClick={reset}>์ด๊ธฐํ</button>
<button onClick={onFilp}>๋ค์ง๊ธฐ</button>
</div>
</div>
);
์กฐ๊ฑด์ ๋ฐ๋ผ compornent๋ฅผ showํ ์ ์๋ค.
const root = document.getElementById("root");
//compornent1
function MinutesToHours() {
const [minutes, setMinutes] = React.useState(0);
const [filpped, setFilpped] = React.useState(false);
const onChange = (event) => {
setMinutes(event.target.value);
};
const reset = () => {
setMinutes(0);
};
const onFilp = () => {
setFilpped((current) => !current);
};
return (
<div>
<div>
<label htmlFor="minutes">Minutes</label>
<input
type="number"
placeholder="Minutes"
id="minutes"
value={filpped ? Math.round(minutes / 60) : minutes}
onChange={onChange}
disabled={filpped}
/>
<label htmlFor="hours">Hours</label>
<input
type="number"
placeholder="Hours"
id="hours"
value={filpped ? minutes : Math.round(minutes / 60)}
onChange={onChange}
disabled={!filpped}
/>
<button onClick={reset}>์ด๊ธฐํ</button>
<button onClick={onFilp}>๋ค์ง๊ธฐ</button>
</div>
</div>
);
}
//compornent2
function KmToMiles() {
return <h3>Km 2 Miles</h3>;
}
//compornent3
//compornent3์์์ ์กฐ๊ฑด์ ๋ฐ๋ผ compornent1,2 render.
function App() {
const [index, setIndex] = React.useState("2");
const onSelect = (e) => {
setIndex(e.target.value);
};
return (
<div>
<h1 className="hi">Super Converter</h1>
<select value={index} onChange={onSelect}>
<option value="0">MinutesToHours</option>
<option value="1">KmToMiles</option>
<option value="2">์ ํํด์ค์</option>
</select>
// jsx๋ฌธ๋ฒ์์๋ {์ค๊ดํธ}์์์ javascript๋ฅผ ์์ฑํ ์ ์๋ค.
// ์ผํญ์ฐ์ฐ์๋ฅผ ์ค์ฒฉ์ผ๋ก ์ฌ์ฉํ๋ค.
{index === "2" ? (
"์ ํํด์ค์"
) : index === "0" ? (
<MinutesToHours />
) : (
<KmToMiles />
)}
</div>
);
}
ReactDOM.render(<App />, root);

๋๊ผฌ์ค์ ์ฑ๋ฆฐ์ง! ํผ์ km to mile ์ปดํฌ๋ํธ ๋ง๋ค์ด๋ณด๊ธฐ.
function KmToMiles() {
const [kmState, setKmState] = React.useState(0);
const [inputAble, setInputAble] = React.useState(false);
const onChange = (e) => {
setKmState(e.target.value);
console.log(e.target.value);
};
const reset = () => {
setKmState(0);
};
const filp = () => {
setInputAble((current) => !current);
};
return (
<div>
<h3>km to mile</h3>
<div>
<label htmlFor="km">ํฌ๋ก๋ฏธํฐ</label>
<input
type="number"
placeholder="ํฌ๋ก๋ฏธํฐ"
id="km"
value={inputAble ? kmState * 1.609 : kmState}
onChange={onChange}
disabled={inputAble}
/>
</div>
<div>
<label htmlFor="mile">๋ง์ผ</label>
<input
type="number"
placeholder="๋ง์ผ"
id="mile"
value={inputAble ? kmState : kmState * 0.609}
onChange={onChange}
disabled={!inputAble}
/>
</div>
<button onClick={reset}>์ด๊ธฐํ</button>
<button onClick={filp}>๋ค์ง๊ธฐ</button>
</div>
);
}

์ฑ๊ณตโจ