React props - ์ปดํฌ๋ํธ ์ฌ์ค์
underdash ์ฝ๋ ๋ฆฌ๋ทฐ ์ ๋ฆฌ(2)
๋ถ๋ชจ ์ปดํฌ๋ํธ๋ก๋ถํฐ ์์ ์ปดํฌ๋ํธ์ ๋ฐ์ดํฐ๋ฅผ ๋ณด๋ผ ์ ์๋๋ก ํ๋ ๋ฐฉ๋ฒ
style์ ๊ฐ๊ณ text๋ง ๋ค๋ฅธ ๋ฒํผ๋ค์ ๋ง๋ค๋ ค๊ณ ํ๋ค.
๊ธฐ๋ณธ์ ์ผ๋ก๋ ๋ค์๊ณผ ๊ฐ์ด ์ผ์ผ์ด ๋ชจ๋ ๋ฒํผ์ ์ปดํฌ๋ํธ๋ฅผ ๋ง๋ค์ด์ style์ ๋ณต๋ถํด์ผ ํ๋ค.
์ค์ง์ ์ผ๋ก ๋ ๋ฒํผ ์ฌ์ด์ ๋ค๋ฅธ ์ ์ text ๋ฐ์ ์๋ค.
const SaveBtn = () => {
return (
<div>
<button
style={{
backgroundColor: "lightsalmon",
color: "white",
border: 0,
borderRadius: 10,
padding: "10px 20px",
}}
>
Save
</button>
</div>
);
};
const ConfirmBtn = () => {
return (
<div>
<button
style={{
backgroundColor: "lightsalmon",
color: "white",
border: 0,
borderRadius: 10,
padding: "10px 20px",
}}
>
Confirm
</button>
</div>
);
};
const App = () => {
return (
<div>
<SaveBtn />
<ConfirmBtn />
</div>
);
};
const root = document.getElementById("root");
ReactDOM.render(<App />, root);
๊ทธ๋ฌ๋ React props๋ฅผ ์ด์ฉํ๋ฉด ๋ถ๋ชจ ์ปดํฌ๋ํธ์ธ App ์ปดํฌ๋ํธ์์ ์์ ์ปดํฌ๋ํธ์ธ Btn ์ปดํฌ๋ํธ์ prop์ ๋๊ฒจ์ค
์ผ๋ก์จ ํ๋์ ๋ฒํผ ์ปดํฌ๋ํธ๋ฅผ ์ฌ์ค์
ํ๋ ๋ฐฉ์์ผ๋ก ์ฌ๋ฌ ๊ฐ์ ๋ค๋ฅธ ์ปดํฌ๋ํธ๋ค์ ๊ตฌํํ ์ ์๋ค.
const Btn = (props) => { // {text, big}
return (
<div>
<button
style={{
backgroundColor: "lightsalmon",
color: "white",
border: 0,
borderRadius: 10,
padding: "10px 20px",
fontSize : props.big ? 18 : 16, // big ? 18 : 16
}}
>
{props.text} // {text}
</button>
</div>
);
};
const App = () => { // ๋ถ๋ชจ ์ปดํฌ๋ํธ์์
return (
<div>
<Btn text="Save" big="true" /> // ์์ ์ปดํฌ๋ํธ ์ฌ์ค์
<Btn text="Confirm" big="false" /> // ใ
</div>
);
};
const root = document.getElementById("root");
ReactDOM.render(<App />, root);
์ปดํฌ๋ํธ๋ ํญ์ Object ๊ฐ์ฒด ํ์์ ํ๋์ ์ธ์๋ง์ ๋ฐ๋๋ค.
Btn ์ปดํฌ๋ํธ์์ console.log(props) ์ ์คํํ๋ฉด {text: Save, big: true} {text: Confirm, big: false} ๊ฐ ์ถ๋ ฅ๋๋ค.
props ๋์ ์ shortcut ํํ์ธ {text , big} ์ ์ธ์๋ก ์ ๋ฌํ ์๋ ์๋ค.
ํํธ, ์์ ์ปดํฌ๋ํธ์์๋ ๋ถ๋ชจ ์ปดํฌ๋ํธ๋ก๋ถํฐ ์ ๋ฌ๋ฐ์ Boolean ๊ฐ์ ๊ฐ์ง๋ ๋ฐ์ดํฐ(big)๋ฅผ ๋ฐํ์ผ๋ก ์ผํญ ์กฐ๊ฑด ์ฐ์ฐ์๋ฅผ ์ฌ์ฉํ ์๋ ์๋ค.
์์ props๋ก string๊ณผ boolean ๊ฐ์ ์ ๋ฌํ๋๋ฐ ํจ์๋ฅผ ์ ๋ฌํ ์๋ ์๋ค.
Btn์ text๋ฅผ App์ state์ ์ฐ๊ฒฐํ๋ค.
state๊ฐ ๋ฐ๋ ๋๋ง๋ค Btn์ text prop์ ๊ฐ์ด ๋ฐ๋๋๋ก App ์ปดํฌ๋ํธ๊ฐ return ํ๋ Btn ์ปดํฌ๋ํธ์ changeValue prop์ ์ถ๊ฐํ ํ Btn ์ปดํฌ๋ํธ์ ์ธ์๋ก changeValue prop์ ์ ๋ฌํ๋ค.
๐ก ์ฃผ์!
App ์ปดํฌ๋ํธ๊ฐ return ํ๋ ์ปค์คํ ์ปดํฌ๋ํธ Btn์
changeValue={changeValue}
์ ์ถ๊ฐํด๋ ์ด๊ฒ์ ์ด๋ฒคํธ ๋ฆฌ์ค๋๊ฐ ์๋๋ผ Btn์ ์ธ์๋ก ์ ๋ฌ๋๋ prop์ผ ๋ฟ์ด๋ค.
onClick={changeValue}
๋ผ๊ณ ํด๋ ๋ง์ฐฌ๊ฐ์ง, onClick ์ด๋ฒคํธ ๋ฆฌ์ค๋์ ๋์ผํ ์ด๋ฆ์ ๊ฐ์ง๋ ์ฌ๊ธฐ์์ onClick์ ๊ทธ์ prop์ผ ๋ฟ์ด๋ค.Btn ์ปดํฌ๋ํธ ์์ HTML ์์ button์
onClick={changeValue}
์ ์ถ๊ฐํด์ผ ์ด๊ฒ์ด ์ค์ ์ด๋ฒคํธ ๋ฆฌ์ค๋๊ฐ ๋๋ค.
onClick={onClick}
๋ผ๊ณ ํด๋ ๋ง์ฐฌ๊ฐ์ง, ์์ onClick์ ์ด๋ฒคํธ ๋ฆฌ์ค๋, ๋ค์ onClick์ prop์ด๋ค.
const Btn = ({text, changeValue}) => {
return (
<div>
<button
onClick={changeValue}
// ์ค๋ต
}}
>
{text}
</button>
</div>
);
};
const App = () => {
const [value, setValue] = React.useState("Save Changes");
const changeValue = () => setValue("Revert Changes");
return (
<div>
<Btn text={value} changeValue={changeValue} />
<Btn text="Continue" />
</div>
);
};
๋ถ๋ชจ ์ปดํฌ๋ํธ์์ ์ด๋ค state๊ฐ ๋ณ๊ฒฝ๋๋ฉด ์์ ์ปดํฌ๋ํธ๊ฐ ๋ถ๋ชจ ์ปดํฌ๋ํธ์ ๋ค๋ฅธ state ๊ฐ์ prop์ผ๋ก ์ฌ์ฉํ๊ณ ์์ด๋ ๋ถ๋ชจ ์ปดํฌ๋ํธ์ state ๋ณ๊ฒฝ์ ์ํด ๋ถ๋ชจ ์ปดํฌ๋ํธ๊ฐ ๋ฆฌ๋ ๋๋ง ๋ ๋ ์์ ์ปดํฌ๋ํธ ๋ํ ๊ฐ์ด ๋ฆฌ๋ ๋๋ง ๋๋ค.
์ด๋ฅผ ๋ฐฉ์งํ๊ณ ์ปดํฌ๋ํธ๋ฅผ ๊ธฐ์ตํ๋๋ก ํจ์ผ๋ก์จ ๋ถ๋ชจ ์ปดํฌ๋ํธ์ state๊ฐ ๋ฐ๋์๋๋ผ๋ ์์ ์ปดํฌ๋ํธ์ prop์ด ๋ฐ๋์ง ์๋๋ค๋ฉด ๋ฆฌ๋ ๋๋ง ๋์ง ์๋๋ก
ํ๊ธฐ ์ํด React.memo()๋ฅผ ์ฌ์ฉํ ์ ์๋ค.
const Btn = ({text, changeValue}) => {
// ์ค๋ต
};
const MemorizedBtn = React.memo(Btn); // ์ถ๊ฐ
const App = () => {
// ์ค๋ต
return (
<div>
<MemorizedBtn text={value} changeValue={changeValue} /> // ์์
<MemorizedBtn text="continue" /> // ์์
</div>
);
};
๋ถ๋ชจ ์ปดํฌ๋ํธ์ state๊ฐ ๋ฐ๋ ๋๋ง๋ค ์๋ฐฑ ์์ฒ ๊ฐ์ ์์ ์ปดํฌ๋ํธ๊ฐ ํญ์ ๋ฆฌ๋ ๋๋ง ๋๋ค๋ฉด ์ดํ๋ฆฌ์ผ์ด์ ์ด ๋๋ ค์ง๋ ์์ธ์ด ๋ ์๋ ์์ผ๋ฏ๋ก ์ปดํฌ๋ํธ์ ๊ฐ์๊ฐ ๋ง์์ง๋ค๋ฉด ์ด๋ฅผ ์ ์ ํ๊ฒ ์ฌ์ฉํ ํ์๊ฐ ์๋ค.
Typecheking With PropTypes ์ฐธ๊ณ
ํ๋์ ์ปดํฌ๋ํธ๊ฐ ๋งค์ฐ ๋ง์ prop์ ๊ฐ์ง ๋ ์๋ชป๋ prop์ ์ ๋ฌํ๋ ๋ฑ์ ๋ฌธ์ ๊ฐ ๋ฐ์ํ ์ ์๋ค.
์๋ฅผ ๋ค์ด, text prop์ ๊ฐ์ผ๋ก string์ด ์๋๋ผ number๋ฅผ ์ ์ด์ค๋ ์ฝ๋ ์์ผ๋ก๋ ๋ฌธ์ ๊ฐ ์๊ธฐ ๋๋ฌธ์ ๊ทธ๋๋ก ์ ์ฉ๋๋ค.
// propType ์ค์น (์ฌ๊ธฐ์ Node.js ์ฌ์ฉ x)
<script src="https://unpkg.com/prop-types@15.7.2/prop-types.js"></script>
propTypes ํจํค์ง๋ ์ค์นํ๋ฉด props๊ฐ ์ด๋ค ํ์
์ด์ด์ผ ํ๋์ง ์ค์
ํ ์ ์๋ค.
์ค์ ํ ํ์
๊ณผ ๋ค๋ฅธ ํ์
์ ๊ฐ์ด ์
๋ ฅ๋๋ฉด ์ฝ์์ ๊ฐ์ด ์๋ชป๋๋ค๊ณ ๊ฒฝ๊ณ ๊ฐ ๋ฌ๋ค.
// propTypes ์๋ฌธ์ p โ
Btn.propTypes = {
text: PropTypes.string.isRequired, // PropTypes ๋๋ฌธ์ p โ
// isRequired๋ฅผ ์ฌ์ฉํ๋ฉด ํด๋น prop์ด ์ง์ ๋์ง ์์ผ๋ฉด ์ฝ์์ ๊ฒฝ๊ณ ์ฐฝ์ ๋์์ค๋ค.
fontSize: PropTypes.number,
};
const App = () => {
const [value, setValue] = React.useState("Save Changes");
const changeValue = () => setValue("Revert Changes");
return (
<div>
<MemorizedBtn text={value} changeValue={changeValue} fontSize={18} />
<MemorizedBtn text="Continue" />
</div>
);
};
์๋ฐ์คํฌ๋ฆฝํธ ๋ฌธ๋ฒ์ ์ํด ๊ธฐ๋ณธ๊ฐ ๋งค๊ฐ๋ณ์๋ฅผ ์ฌ์ฉํ ์ ์๋ค.
prop์ ๊ฐ์ด undefined์ธ ๊ฒฝ์ฐ ์ค์ ํ ๊ธฐ๋ณธ๊ฐ์ด ํ ๋น๋๋ค.
const Btn = ({ text, changeValue, fontSize = 14 }) => {
// ์ค๋ต
};
๐ ์ฒ์์ ์์ฑํ ์ฝ๋ (์์ ์ )
์ ์ฌ ๋ฐฐ์ด์ธ arguments๋ฅผ ํ์ฉํ๋ค.
์ค์ฒฉ for ๋ฌธ์ด ์ฌ์ฉ๋๊ณ ์๋ค.
_.extend = function (obj) {
for (let i = 1; i < arguments.length; i++) {
for (key in arguments[i]) {
obj[key] = arguments[i][key];
}
}
return obj;
};
๐ _.each ํจ์๋ฅผ ์ฌํ์ฉํ์ฌ ์์ฑํ ์ฝ๋
๊ทธ๋ฅ for ๋ฐ๋ณต๋ฌธ ๋์ _.each ํจ์๋ก ๋์ฒดํ ๊ฒ๋ฟ์ด๋ค.
๋ญ๊ฐ ๊ฐ์ ํ๋ค๊ธฐ์ ๋๋ฌด ๋น์ฝํด ๋ณด์ฌ์ ๋ค๋ฅธ ๋ฐฉ๋ฒ์ ์ฌ์๋ํ๋ค.
_.extend = function (obj, ...args) {
_.each(args, function (object) {
_.each(object, function (value, key) {
obj[key] = object[key];
});
});
}
๐ ๋๋จธ์ง ๋งค๊ฐ๋ณ์
์ _.each ํจ์, _.reduce ํจ์๋ฅผ ์ฌํ์ฉ
ํ์ฌ ์์ฑํ ์ฝ๋
- ๋ฏธ๋ฆฌ ๊ตฌํํด๋์
_.each
ํจ์์_.reduce
ํจ์_.each = function (collection, iterator) { if (Array.isArray(collection)) { for (let i = 0; i < collection.length; i++) { iterator(collection[i], i, collection); } } else { for (key in collection) { if (collection.hasOwnProperty(key)) { iterator(collection[key], key, collection); } } } }; _.reduce = function (collection, iterator, accumulator) { if (accumulator !== 0 && accumulator === undefined) { accumulator = collection[0]; for (let i = 1; i < collection.length; i++) { accumulator = iterator(accumulator, collection[i]); } } else { for (key in collection) { if (collection.hasOwnProperty(key)) { accumulator = iterator(accumulator, collection[key]); } } } return accumulator; };
_.extend
ํจ์ ์์ _.extend = function (obj, ...args) { obj = _.reduce( args, function (acc, curr) { _.each(curr, function (value, key) { acc[key] = curr[key]; }); return acc; }, obj ); return obj; };
ํจ์ ์ฌํ์ฉ์ ์ฐ์ต ์ค์ด๋ผ ์ผ๋จ ์์ ํด๋ณด๊ธด ํ๋๋ฐ ์์ ์ ์ฝ๋๊ฐ ๋ ์ ์ฝํ๋ ๊ฑฐ ๊ฐ์ ๊ฑด ๋ด๊ฐ ๋ด๊ณต์ด ๋ถ์กฑํด์์ผ๊น...
_.extend ํจ์๋ฅผ ์์ ํ ๋ฐฉ์๊ณผ ๊ฐ์ ๋ฐฉ์์ผ๋ก ์์ ํ๋ค.
๐ ์ฒ์์ ์์ฑํ ์ฝ๋
_.defaults = function (obj) {
for (let i = 1; i < arguments.length; i++) {
for (key in arguments[i]) {
if (key in obj) {
continue;
}
obj[key] = arguments[i][key];
}
}
return obj;
};
๐ ๋๋จธ์ง ๋งค๊ฐ๋ณ์
์ _.each ํจ์, _.reduce ํจ์๋ฅผ ์ฌํ์ฉ
ํ์ฌ ์์ฑํ ์ฝ๋
_.defaults = function (obj, ...args) {
obj = _.reduce(
args,
function (acc, curr) {
_.each(curr, function (value, key) {
if (key in acc) return; // _.extend ํจ์์์ ์ด ๋ถ๋ถ๋ง ์๋กญ๊ฒ ์ถ๊ฐํจ
acc[key] = curr[key];
});
return acc;
},
obj
);
return obj;
};
์ฌ๊ท ํจ์๋ ๋ช ์์ ์ธ return ๊ฐ์ ๊ฐ์ง๋ ์ฌ๊ทํจ์์ ๊ทธ๋ ์ง ์์ ์ฌ๊ท ํจ์๋ฅผ ํฌํจํ์ฌ ํฌ๊ฒ 2๊ฐ์ง๋ก ๋๋ ์ ์๋ค.
function deleteItem (arr) {
if (arr.length === 0) {
return;
}
arr.pop();
const newArr = arr;
deleteItem(newArr);
}
const hi = [1, 2, 3];
deleteItem(hi);
console.log(hi); // []
_.flatten
ํจ์๋ ๋ช
์์ ์ธ return ๊ฐ์ ๊ฐ์ง๋ ์ฌ๊ท ํจ์์ด๋ค.
์ด ๊ฒฝ์ฐ ์ฌ๊ท ํจ์๋ฅผ ์คํ์ํจ ํ ๊ทธ return ๊ฐ์ ๋ฐ์์ ์ฌ์ฉ
ํด์ผ๋ง ์๋ฏธ๊ฐ ์๋ค.
_.flatten = function (nestedArray) {
// Hint: Use Array.isArray to check if something is an array
const flattenedArray = [];
for (let i = 0; i < nestedArray.length; i++) {
if (!Array.isArray(nestedArray[i])) {
flattenedArray.push(nestedArray[i]);
} else {
const innerFlattedArray = _.flatten(nestedArray[i]); // ์ฌ๊ท ํจ์ return๊ฐ์ ๋ณ์ innerFlattedArray์ ๋ฐ์
flattenedArray.push(...innerFlattedArray); // ๊ทธ ๊ฐ์ ์ฌ์ฉํ๋ ์ฝ๋
}
}
return flattenedArray;
};
CREATE REACT APP
underdash ์ฝ๋ ์ต์ข ์ ๋ฆฌ ํ commit & push