whatisthis?
220317 [TIL] Today I Learned ๐ฏ React.js ๋ณธ๋ฌธ
React.js
๐ฉ ๋ชฉ์ฐจ
- ํด๋์คํ ์ปดํฌ๋ํธ
- ํจ์ํ ์ปดํฌ๋ํธ
- ๋ฐฐ์ด ์ปดํฌ๋ํธ
- ์ปดํฌ๋ํธ์์์ ์ฝ๋ฐฑ๊ณผ ์ด๋ฒคํธ๋ฆฌ์ค๋
ํด๋์คํ ์ปดํฌ๋ํธ
์๋ช ์ฃผ๊ธฐ ๋ฉ์๋์ ์ปดํฌ๋ํธ ๊ตฌ์ฑ์์๋ฅผ ๋ชจ๋ ํฌํจํ๋ ํด๋์คํ ์ปดํฌ๋ํธ.
์ด ๋๊ฐ์ง ์ข ๋ฅ์ ํด๋์ค๋ฅผ ์ฌ์ฉ.
- Component
- PureComponent
1 / Component ํด๋์ค
- props, state, life-cycle method๊ฐ ๋ค์ด์๋ ๊ตฌ์กฐ์ ์ปดํฌ๋ํธ
2 / PureComponenet ํด๋์ค
- Component ํด๋์ค๋ฅผ ์์๋ฐ์ ํด๋์ค.
- shouldComponentUpdate() ํจ์๋ฅผ ์์ ๋น๊ต๋ฅผ ํ๋๋ก ์ฌ์ ์.
๐ shouldComponentUpdate(nextProps, nextState)
ํ๋กํผํฐ๋ฅผ ๋ณ๊ฒฝํ๊ฑฐ๋ setState()๋ฅผ ํธ์ถํ์ฌ state๋ฅผ ๋ณ๊ฒฝํ๋ฉด
๋ค์ ๋ ๋๋งํด์ผํ๋์ง ํ๋จํ๋ ํจ์.
์ฆ, ๋ฆฌ๋ ๋๋ง ํ ์ง ๋ง์ง ํ๋จ. ํ๋ฉด ๋ณ๊ฒฝ์ ์ํ ๊ฒ์ฆ ์์ .
๋ฐ์ดํฐ ๋ณํ๋ฅผ ๋น๊ตํ๋ ์์ ํฌํจ๋จ. (์ฑ๋ฅ์ ์ํฅ ๅค)
- ์์ ๋น๊ต๋ฅผ ํตํด ๋ฐ์ดํฐ๊ฐ ๋ณ๊ฒฝ๋ ๊ฒฝ์ฐ์๋ง render()์ ํธ์ถํจ.
- ๐ reactjs.org/docs
React.PureComponent is similar to React.Component.
The difference between them is that React.Component doesn’t implement shouldComponentUpdate(),
but React.PureComponent implements it with a shallow prop and state comparison.
๐โ๏ธ ์์ ๋น๊ต(shallowCompare) ๋?
const list1 = [1, 2, 3, obj]; const list2 = [1, 2, 3, obj];
- ์์ ๋น๊ต์์ list1๊ณผ list2๋ ๊ฐ๋ค.
- cf. ๊น์ ๋น๊ต (===)์์๋ list1๊ณผ list2๋ reference๊ฐ ๋ค๋ฅด๋ฏ๋ก ๋ค๋ฅด๋ค.
___
shallowCompare๋ ํ์ฌ ์ํ ๋ฐ nextState ๊ฐ์ฒด๋ฟ ์๋๋ผ
ํ์ฌ props ๋ฐ nextProps ๊ฐ์ฒด์ ๋ํด ์์ ๋๋ฑ์ฑ ๊ฒ์ฌ๋ฅผ ์ํํฉ๋๋ค.
์์ ๋น๊ต๋ ๋๋ฑ์ฑ์ ํ์ธํฉ๋๋ค.
์ค์นผ๋ผ ๊ฐ (์ซ์, ๋ฌธ์์ด)์ ๋น๊ตํ ๋๋ ๊ฐ์ ๋น๊ตํฉ๋๋ค.
๊ฐ์ฒด๋ฅผ ๋น๊ตํ ๋ ๊ฐ์ฒด์ ์์ฑ์ ๋น๊ตํ์ง ์์ต๋๋ค. ์ฐธ์กฐ(Reference) ๋ง ๋น๊ต๋ฉ๋๋ค.
>> ๋์ผํ ๊ฐ์ฒด๋ฅผ ๊ฐ๋ฆฌํค๋์ง.
- shallow compare ์์
object๋ค์ ๋ ํผ๋ฐ์ค๋ง ์ฒดํฌํ๊ธฐ๋๋ฌธ์ ๊ฐ์ ๊ฐ์ด ๋ค์ด์๋ object์ด๋๋ผ๋ ํญ์ ๋ค๋ฅธ๊ฐ์ผ๋ก ์ฒดํฌํ๊ฒ ๋ฉ๋๋ค.
Component | ํญ์ render()ํจ์ ํธ์ถ |
PureComponent | ์์ ๋น๊ต๋ฅผ ํตํด ๋ฐ์ดํฐ๊ฐ ๋ณ๊ฒฝ๋ ๊ฒฝ์ฐ์๋ง render() ํธ์ถ |
โ React.PureComponent๋ฅผ ์ฌ์ฉํ ์ ์๋ ์ํฉ
1. state์ prop์ด immutable์ผ๋
( scalar ๊ฐ๋ค์ shallow compare๋ก ๊ฐ์ ๋น๊ตํ๊ธฐ ๋๋ฌธ์ ์๊ด์์ง๋ง
object๋ค์ reference๋ก ๋ค๋ฆ์ ์ฒดํฌํ๊ธฐ ๋๋ฌธ์ ์ ์ ์น ๋ชปํ๊ฒ ์ฌ์ฉ๋ ์ ์์)
2. state์ prop์ด ๊ณ์ธต(hierarchy) ํน์ ๋ณต์กํ ๊ตฌ์กฐ๋ฅผ ๊ฐ์ง๊ณ ์์ง ์์๋
3. shouldComponentUpdate lifecycle์ ์ฌ์ฉํ์ง ์์ ๊ณํ์ผ๋
shallowCompare์ ์ํด shallow-equal ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ shallowEqual() ํจ์๋ฅผ ์ด์ฉ.
import React from 'react';
import shallowEqual from 'shallow-equal';
export class PureComponent extends React.Component {
shouldComponentUpdate(nextProps, nextState) {
return !shallowEqual(this.props, nextProps) ||
!shallowEqual(this.state, nextState)
}
}
// ref๊ฐ ๋ฌ๋ผ๋ ๊ฐ์ด ๊ฐ๋ค๋ฉด true๋ฅผ ๋ฐํํ๋ฏ๋ก, return (!true || !true)๊ฐ ๋จ
// props๋ state ๋์ค ํ๋๋ง ์๋ณํด๋(์ฆ, ๊ฐ์๋) return false
// shouldComponentUpdate()๊ฐ false๋ฅผ return ํ๋ฏ๋ก render()๊ฐ ์คํ ์๋จ!
// โ shouldComponentUpdate()๊ฐ true์ฌ์ผ ๋ค์ (life-cycle)๊ณผ์ ์ธ render()์ ์งํํ๋ฏ๋ก
โช PureComponent ํด๋์ค๋ก ์ ์ธํ ์ปดํฌ๋ํธ์์๋
shouldComponentUpdate()์์ shallowEqual()ํจ์๋ก ์์ ๋น๊ต๋ฅผ ํ์ฌ
๋ฐ์ดํฐ์ ๋ณ๊ฒฝ์ด ์์ผ๋ฉด - ํ๋ฉด ์๋ก ์ถ๋ ฅ - render()ํธ์ถํจ
๋ฐ์ดํฐ์ ๋ณ๊ฒฝ์ด ์์ผ๋ฉด - return false - render()ํธ์ถ ์ํจ
โช Component ํด๋์ค๋ก ์ ์ธํ ์ปดํฌ๋ํธ๋ ๋น๊ต๊ณผ์ ์์ด ํญ์ ์๋ก ๋ ๋๋งํจ.
(๋ฐ์ดํฐ์ ๋ณ๊ฒฝ์ด ์๋ ๋ง๋ ~)
๐
์ฑ์ ์ฑ๋ฅ์ ์ต๋ํ ํ๊ธฐ ์ํด
PureComponent์ ๋ถ๋ณ ๋ณ์๋ฅผ ์ฌ์ฉ.
- ์> ์์ด๋น์ค๋น์์
์์ ์ ๋ณด๊ฐ 10000๊ฐ๊ฐ ์๋ค๋ฉด, 1๊ฐ์ ์ ๋ณด๋ง ์์ ํ์ ๋๋ง๋ค
9999๊ฐ์ ์์ ์ ๋ณด๋ฅผ ๋น๊ตํ๋ฉด ๋นํจ์จ์ ์.
- ์ ๋ณด๊ฐ ๋ฐ๋ ๋ ๋ง๋ค ์ ๋ฐฐ์ด์ ํ ๋นํ๋ ๋ฐฉ์์ผ๋ก
๋น๊ต์๋๋ฅผ ์ต์ ํ ํ ์ ์์
๐ป ์ฑ ์์ ์ดํด ์๊ฐ์ ํผ์ ์ฃผ์ ๋ฆฌ ๐
๋ต:
MyComponent ์๋ก๊ณ ์นจ
MyComponent ์๋ก๊ณ ์นจ
MyPureComponent ์๋ก๊ณ ์นจ
__
์ด๋ผ๊ณ ํ๋๋ฐ, ์ ๊ทธ๋ฐ์ง ๋ชจ๋ฅด๊ฒ ๋ค.
์ฒซ๋ฒ์งธ๋ก setTimeout() ์ฒ์๊บผ๋ฅผ ์คํํ๋ฉด
this.listValue[0].name = 'Justin'; ์ผ๋ก props๋ฅผ ์์ ํ๋ค.
์ฌ๊ธฐ์ MyComponent๋ ๋ฌด์กฐ๊ฑด ๋ฆฌ๋ ๋๋ง ํ๋๊น passํ๊ณ
MyPureComponent๋ ์์๋น๊ต๋ก ํ์ผ๋ props๊ฐ ๋ณํ ๊ฒ ์๋๊ฐ?
state๋ ๋ณํ๊ฒ์ด๊ณ .
๊ทผ๋ฐ ์ด๊ฒ ์๋ง props๋ ์๋ณํด์ - return falseํด์ - ๋ ๋๋ง ์๋จ
์ด๋ ๊ฒ ๊ตฌํ์ด ๋์ด์ ์ ๋ต์ด ์ ๋ ๊ฒ ๋ ๊ฒ ๊ฐ์๋ฐ,
๋ด์๊ฐ์ ...
์๋ก ๋ฐฐ์ด์ ํ ๋นํ๋๊ฒ ์๋๊ณ ์์ผ listValue์ ์ฒซ๋ฒ์งธ ์์์ ๊ฐ๋ง ๋ฐ๋๊ฑฐ๋๊น
์์ ๋น๊ต๋ก๋ ์ ๊ฒ ์๋ณํ๊ฑธ๋ก ์น๋๋ณด๋ค. ์ฆ,
return !shallowEqual(this.props, nextProps) ||
!shallowEqual(this.state, nextState)
}
์ด๋ถ๋ถ์์ this.props ๋ nextProps๊ฐ ๊ฐ๋ค! Equal!๋ก ํ๋ช ๋๊ณ
this.state๋ nextState๋ ๊ฐ์ด ํ์คํ ๋ฌ๋ผ์ก์ผ๋ฏ๋ก Equal์ด ์๋๊ณ .
return !true || !false ํด์ false๊ฐ ๋ฆฌํด๋๋ฏ. (state๋ ๋ณํ์ด๋ props๊ฐ ์ ๋ณํ์)
๊ทธ๋์ ์ฒซ๋ฒ์งธ setTimeout์์ PureComponent๋ ๋ ๋๋ง ์๋๊ฒ.
์ฒ์์ ์ฒซ๋ฒ์งธ setTimeout์์
MyComponent ์๋ก๊ณ ์นจ
MyPureComponent ์๋ก๊ณ ์นจ
๊ฐ ๋์จ๋ค๊ณ ์์ํ๋ค.
์ด์ ๋๋ฒ์งธ setTimeout()์ ๋ณด๋ฉด
this.listValue, ์ฆ props๋ฅผ ์์ ๋ฐฐ์ดํํ๋ก ์๋ก ๋์ (=)์ ํด๋ฒ๋ ธ์ผ๋
์ด๊ฑด ๊ฐ์ด ๋ฐ๋๊ฑฐ๋ผ๊ณ ๋ณด๋ฉด ๋๋ค.
์ด์ ๋ณด๋ฉด props๋ ๋ณํ๊ณ , state๋ ๋ณํ๋ค.
return !false || !false ํด์ true๋ฅผ ๋ฆฌํดํ ๊ฒ.
๐ key point
this.listValue = [{name: 'Park'}, {name: 'Lee'}]; ์ผ๋,
1๏ธโฃ this.listValue[0].name = 'Justin';
- ๋ฐฐ์ด ์์ ๊ฐ์ฒด์ ์์ฑ๊ฐ์ด ๋ฐ๋๊ฑฐ์.
- ์ฆ, ๋ฐฐ์ด(listValue)์ด ๋ฐ๋๊ฑด ์๋. ์์ ๋น๊ต๋ฅผ ํ๋ฉด ์๋ this.props = nextProps
2๏ธโฃ this.listValue = [{name: 'Justin'}, {name: 'Lee'}];
- ๋ฐฐ์ด ์์ฒด๋ฅผ ๋์ (=)์ผ๋ก ๋ฐ๊ฟ๋ฒ๋ฆผ.
- ์์ ๊ฐ์ ๊ฐ์์ง ๋ชฐ๋ผ๋, listValue ์์ฒด๊ฐ ์๋ก ์ ์ธ๋์์ผ๋ฏ๋ก this.props != nextProps.
ํจ์ํ ์ปดํฌ๋ํธ
- state๊ฐ ์๋ ํจ์ํ ์ปดํฌ๋ํธ (SFC)
- React.StatelessComponent์ธ๋ฐ, ์ค์ฌ์ SFC๋ก ์ฌ์ฉ ๊ฐ๋ฅ.
- state๋ฅผ ํฌํจํ์ง ์์ผ๋ฉฐ, ๋ฐ์ดํฐ๋ฅผ ๋ฐ์ ์ถ๋ ฅํ ์ปดํฌ๋ํธ๋ฅผ ๋ฐํํจ.
๋ฐ์ดํฐ(prop, context) => ํจ์ํ ์ปดํฌ๋ํธ => ์ถ๋ ฅํ ์ปดํฌ๋ํธ (JSX)
- state๊ฐ ์๊ณ , ํ๋กํผํฐ์ ์ปจํ ์คํธ๋ง์ผ๋ก ํ๋ฉด์ ๊ตฌ์ฑํ๋ฏ๋ก ๋จ์ํ ๊ตฌ์กฐ์ UI ์ปดํฌ๋ํธ๋ฅผ ์ ์ํ ๋ ์ฃผ๋ก ์ฌ์ฉ.
- ์๋ช ์ฃผ๊ธฐ ํจ์๋ ์ฌ์ฉํ ์ ์์.
function TodaysPlanApp(props) {
const { onButtonClick, hasPlan } = props;
return (
<div>
{hasPlan ? <TodaysPlanApp /> : null}
<button onClick={onButtonClick}>๊ณํ ์์</button>
</div>
);
}
export default TodaysPlanApp;
onButtonClick ํจ์์ hasPlan์ props๋ก ๋ฐ๊ณ ,
hasPlan์ด true๋ฉด ๋ ๋๋งํ๊ณ , false๋ฉด ๋ ๋๋งํ์ง ์์.
๋ฐฐ์ด ์ปดํฌ๋ํธ
- ๊ฒ์ํ or ์ ํ๋ธ ์์ ๋ชฉ๋ก ๋ฑ์ ๊ตฌํ.
- ์๋ฐ์คํฌ๋ฆฝํธ ๋ฐฐ์ด(array) ์ฌ์ฉ
๋ฐฐ์ด ์์ ๋ค์ํ ์๋ฃํ์ ์ ์ฅํ ์ ์์
>> JSX๋ ๋ฐฐ์ด์ ์ ์ฅ ๊ฐ๋ฅ.
map()ํจ์๋ฅผ ์ด์ฉํ์ฌ ์ฌ๋ฌ ํ๋ฉด์ ์์ฝ๊ฒ ์ถ๋ ฅ(rendering) ๊ฐ๋ฅ.
const toDoList = [
{ taskName: "๋นจ๋ํ๊ธฐ", finished: false },
{ taskName: "๊ณต๋ถํ๊ธฐ", finished: true },
];
const toDos = toDoList.map(todo => <li>{todo.taskName}</li> );
// JSX๋ก ๋ณ๊ฒฝ๋ ๊ฐ๋ฅ
const toDos = toDoList.map(todo => <TodoTask taskname={todo.taskName} />);
// return ๋ถ๋ถ
return(
<div>
<ul>
{toDos}
</ul>
</div>
๐โ๏ธ map() ์ด์ฉํ์ฌ ๋ฐฐ์ด ์ปดํฌ๋ํธ ์ถ๋ ฅ
- ๋ฐ๋ก render() ์์์ map()ํจ์๋ก ์ถ๋ ฅํ๋ ๋ฐฉ๋ฒ.
render() {
const toDoList = [
{ taskName: "๋นจ๋ํ๊ธฐ", finished: false },
{ taskName: "๊ณต๋ถํ๊ธฐ", finished: true },
];
return (
<div>
<ul>
{toDoList.map(todo => <li> {todo.taskName} </li>);}
</ul>
</div>
);
}
โโ ์ฃผ์์ฌํญ
- ๋ฐฐ์ด ์ปดํฌ๋ํธ๋ ๋ฐฐ์ด ์์์ ๊ฐ์๋งํผ map์ ์ํด ๋ฐ๋ณต๋๋ฏ๋ก ์ฑ๋ฅ์ ์ํฅ์ ๋ง์ด ์ค๋ค.
- ๋ฐ๋ผ์ ๋ฐฐ์ด ์ปดํฌ๋ํธ์๋ ๊ผญ key๊ฐ์ ์ ์ํด์ค์ผํ๋ค.
- ์ถ๋ ฅํ ๋ฐฐ์ด ์ปดํฌ๋ํธ๋ ๋ค์ ์ถ๋ ฅํด์ผํ๋ ๊ฒฝ์ฐ, ๋ฆฌ์กํธ๊ฐ ๊ธฐ์กด ์ปดํฌ๋ํธ๋ฅผ ์ฌํ์ฉํจ.
render() {
const toDoList = [
{ taskName: "๋นจ๋ํ๊ธฐ", finished: false },
{ taskName: "๊ณต๋ถํ๊ธฐ", finished: true },
];
return (
<div>
<ul>
{toDoList.map(todo, index => <li key={`list_${index}`}> {todo.taskName} </li>);}
</ul>
</div>
);
}
- ํค๊ฐ์ผ๋ก ๊ณ ์ ํ ๋ฐฐ์ด ํญ๋ชฉ์ ์ฌ์ฉํด์ผ ๋นํจ์จ ๋ฌธ์ ๊ฐ ํด๊ฒฐ๋จ.
(์์์ฒ๋ผ ์ธ๋ฑ์ค ๋ฒํธ๋ฅผ ํค๋ก ์ฌ์ฉํ๋ค๋ฉด, ๋ง์ฝ ๋์ค์ ํญ๋ชฉ์ด ์ฌ๋ผ์ง๊ฒ ํด์ ์ธ๋ฑ์ค๊ฐ ์ฌ๋ผ์ง๋ฉด, ํค๊ฐ๋ ์ฌ๋ผ์ง.)
- taskName์ ๊ณ ์ ํ ๊ฐ์ด ๋ค์ด์์ผ๋ฏ๋ก, ์ด๋ฅผ ํค๊ฐ์ผ๋ก ์ฌ์ฉํ๋ฉด ์ข๋ค.
๊ฒฐ๋ก : key๊ฐ์ผ๋ก ๋ฌด์กฐ๊ฑด index๋ฅผ ์ด๋ค? - ๋น์ถ์ฒ.
๐ป key๊ฐ์ผ๋ก taskName์ ์ฌ์ฉ
render() {
const toDoList = [
{ taskName: "๋นจ๋ํ๊ธฐ", finished: false },
{ taskName: "๊ณต๋ถํ๊ธฐ", finished: true },
];
return (
<div>
<ul>
{toDoList.map(todo, index => <li key={todo.taskName}> {todo.taskName} </li>);}
</ul>
</div>
);
}
๐โ๏ธ render()์์ ์ฌ๋ฌ๊ฐ์ JSX ๋ ธ๋ ๋ฐํ
- render()์ ํธ๋ฆฌ๊ตฌ์กฐ์ ๋ ธ๋๋ฅผ ๋ฐํํจ.
- ๋ฆฌ์กํธ๋ ํธ๋ฆฌ ๋ง๊ณ ๋ ๋ฐฐ์ด๊ตฌ์กฐ์ ๋ ธ๋๋ฅผ ๋ฐํํ ์ ์์!
์> <button type="button"> Click! </button>
์ 3๊ฐ๋ฅผ ๋ฐํํ๊ณ ์ถ์ ๋
...
render() {
return (
<button type="button"> Click! </button>
<button type="button"> Click! </button>
<button type="button"> Click! </button>
)
}
// โ Error
๋ฆฌ์กํธ 16.3 ๊น์ง๋ render()ํจ์๋ ํธ๋ฆฌ๊ตฌ์กฐ์ ๋ ธ๋ 1๊ฐ๊น์ง๋ง ๋ฐํํ ์ ์๊ณ ,
์ฌ๋ฌ ๋ ธ๋๋ฅผ ๋ฐํํ๋ ค๋ฉด ์๋ฏธ์๋ <div>๋ก ๊ฐ์ธ์ค์ผ ํ๋ค.
๋ฆฌ์กํธ 16.3 ์ดํ๋ก๋ React.Fragment ์ปดํฌ๋ํธ์ ์ถ๊ฐ๋ก,
์๋ฏธ์๋ ๋ ธ๋๋ฅผ ์ถ๊ฐํ๋ ๊ฒ์ ๊ฐ์ ํ์๋ค.
React.Fragement
์ฌ๋ฌ ๋ ธ๋๋ฅผ ์ฌ์ฉํ ๋ ๋ฐํ.
์ด ์ปดํฌ๋ํธ๋ HTML ๋ก ๋ณํ๋์ง ์์.
render() {
return (
<React.Fragment>
<button></button>
<button></button>
<button></button>
</React.Fragment>
);
}
render() {
return (
<>
<button></button>
<button></button>
<button></button>
</>
);
}
<React.Fragment> </React.Fragment>
๋๋
<> </>
๋ก ์ฌ๋ฌ ๋ ธ๋๋ฅผ ๊ฐ์ธ์ฃผ๋ฉด ๋๋ค!
+) map์ ์ฌ์ฉ
render() {
return [1,2,3].map((num) => (
<input type="radio" name="option1" key={`${num}`} value={num} />
))
}
์ปดํฌ๋ํธ์์์ ์ฝ๋ฐฑ๊ณผ ์ด๋ฒคํธ๋ฆฌ์ค๋
ํ๋กํผํฐ (props) ์ฌ์ฉ์ - ์์ ์ปดํฌ๋ํธ์ ๋ฐ์ดํฐ๋ฅผ ํ์ ์ปดํฌ๋ํธ์ ์ ๋ฌ ๊ฐ๋ฅ. (Read Only)
๋ง์ฝ, ํ์ ์ปดํฌ๋ํธ์์ ํ๋กํผํฐ๋ฅผ ๋ณ๊ฒฝํด์ผ ํ ๋๋?
- ํ๋กํผํฐ ์๋ณธ์ ์์ ํ ์ ์๋ ์ฝ๋ฐฑํจ์๋ฅผ ํ์ ์ปดํฌ๋ํธ์ ๊ฐ์ด ๋๊ฒจ์ค.
๐ก ์ฝ๋ฐฑ ํจ์
- ์ ์๋ ์์น์์ ์คํ๋์ง ์๊ณ , ์ดํ ํน์ ์ํฉ์์ ์คํ๋๋ ํจ์
์์ - Counter
App.jsx
import React from 'react';
import Counter from "./Counter";
class App extends Component {
state = {
count: 1,
};
increaseCount = () => {
this.setState(({ count }) => ({ count: count + 1 }));
};
render() {
return <Counter count={this.state.count} />;
}
}
export default App;
์ง๊ธ์ App์ปดํฌ๋ํธ์์ state๋ก ๊ด๋ฆฌํ๋ count๊ฐ์ ๋ณ๊ฒฝํ ์ ์์ง๋ง,
ํ์ ์ปดํฌ๋ํธ์ธ Counter ์ปดํฌ๋ํธ์์ count๋ฅผ ๋ณ๊ฒฝ์ํฌ ์ ์๋ค.
(๊ทธ์ props
๋ก count๋ฅผ ๋ฐ์์ ํ๋ฉด์ ๋ณด์ด๊ฒ๋ง ํ ์ ์์)
App ์ปดํฌ๋ํธ์์ increaseCount()ํจ์๋ฅผ ํ๋กํผํฐ ํํ๋ก ์ ๋ฌํ๋ฉด - Counter์์๋ ๋ณ๊ฒฝ ๊ฐ๋ฅ!
render() {
return <Counter count={this.state.count} onAdd={this.increaseCount} />;
}
์ด๋ฐ์์ผ๋ก props๋ก ์ ๋ฌํด์ฃผ๊ณ , ํ์ ์ปดํฌ๋ํธ์ธ Counter์์๋
Counter.jsx
import React from "react";
import PropTypes from "prop-types";
class Counter extends Component {
render() {
return (
<div>
ํ์ฌ ์นด์ดํธ: {this.props.count}
<button onClick={() => this.props.onAdd()}>์นด์ดํธ ์ฆ๊ฐ</button>
</div>
);
}
}
Counter.propTypes = {
count: PropTypes.number,
onAdd: PropTypes.func,
};
export default Counter;
<button onClick={() => this.props.onAdd()}>์นด์ดํธ ์ฆ๊ฐ</button>
์ด๋ถ๋ถ์ ๋ณด๋ฉด, onClick = {() => this.props.onAdd()}์ ๊ฐ์ด ์ฝ๋ฐฑ์ ํํ๋ก (arrow function) ์์ฑํด์ค๋ค.
๊ทธ๋ฌ๋, ์ด๋๋ก ๋ฒํผ์ ํด๋ฆญํ๋ฉด ์ค๋ฅ๊ฐ ๋ฐ์ํ๋๋ฐ,
์ด๋ ํ์ ์ปดํฌ๋ํธ์์ ์ฐธ์กฐํ this์ ๋ฒ์์ ๋ํ ์ค๋ฅ ๋๋ฌธ์ด๋ค.
์์->ํ์๋ก ์ฝ๋ฐฑํจ์๋ฅผ props๋ก ๋ณด๋ด๋ ๊ฒฝ์ฐ์๋
ํ์ ์ปดํฌ๋ํธ์์ ์ฐธ์กฐํ this ๋ฒ์๋ฅผ bind()๋ก ์ง์ ํด์ค์ผํ๋ค.
App.jsx ์์
import React from 'react';
import Counter from "./Counter";
class App extends Component {
constructor(props) {
super(props);
this.increateCount = this.increateCount.bind(this);
}
state = {
count: 1,
};
increaseCount = () => {
this.setState(({ count }) => ({ count: count + 1 }));
};
render() {
return <Counter count={this.state.count} />;
}
}
export default App;
- ์ปดํฌ๋ํธ์์ window.addEventListner() ํจ์์ ๊ฐ์ DOM๊ฐ์ฒด ํจ์๋ฅผ ์ด์ฉํ๋ ค๋ฉด
DOM๊ฐ์ฒด๋ฅผ ์ปดํฌ๋ํธ ๋ณ์์ ํ ๋นํด์ผํจ.
>> ref๋ฅผ ์ฌ์ฉํ์.
import React from "react";
export default class ScrollSpy extends React.PureComponent {
constructor(props) {
super(props);
this.setRef = this.setRef.bind(this);
this.checkPosition = this.checkPosition.bind(this);
window.addEventListener("scroll", this.checkPosition);
}
setRef(ref) {
this.ref = ref;
}
checkPosition() {
if (this.ref.getBoundingClientRect().top < window.innerHeight) {
console.log("enter"); // ํ์ฌ ์คํฌ๋กค ํ๋ฉด ์ํ์ธ์ง ์ธก์
} else {
console.log("exit");
}
}
componentDidMount() {
this.checkPosition();
}
componentWillUnmount() {
window.removeEventListener("scroll", this.checkPosition);
}
render() {
return <div ref={this.setRef} />;
}
}
- ์๋์ฐ์ ์คํฌ๋กค ์ด๋ ์ด๋ฒคํธ์ >> checkPosition ์คํ
- ref ํ๋กํผํฐ์์ ๋ฐํ๋ ๊ฐ์ฒด๋ฅผ this.ref ๋ณ์์ ํ ๋น.
return <div ref={this.setRef} />๋ก
this.setRef์ ์ธ์๋ก ํด๋น DOM๊ฐ์ฒด๊ฐ ์ ๋ฌ๋๊ณ , this.ref
(์ปดํฌ๋ํธ ๋ณ์)์ ํด๋น ๊ฐ์ฒด๋ฅผ ํ ๋นํด์ค.
props๋ก ์ ๋ฌ๋ ์ฝ๋ฐฑํจ์๋
onClick = {this.resetCount} ์ ๊ฐ์ด ์ฌ์ฉ ๊ฐ๋ฅ.
์ ๋ฆฌ
๋ฆฌ์กํธ ์ปดํฌ๋ํธ๋? ๋จ๋ฐฉํฅ ํ๋ฆ ๋ฐฉ์
state์ ๊ฐ์ ๋ฐ์ดํฐ๋ฅผ ์์->ํ์๋ก ์ ๋ฌ. (props)
๐โ๏ธ props๋ฅผ ๋ณ๊ฒฝํ๋ ค๋ฉด?
์ฝ๋ฐฑํจ์๋ฅผ ํธ์ถํ์ฌ ์๋ณธ ๋ฐ์ดํฐ๊ฐ ์์นํ ์์ ์ปดํฌ๋ํธ์์ ๋ฐ์ดํฐ๋ฅผ ๋ณ๊ฒฝํ๊ณ
๋ค์ ์์ ์ปดํฌ๋ํธ๋ก ์ ๋ฌํ๋๋ก ํจ.
๋จ๋ฐฉํฅ ํ๋ฆ ๋ฐฉ์ - ๋ฐ์ดํฐ ๋ฌด๊ฒฐ์ฑ ์ง์ผ์ค.
๋ฐ์ดํฐ ์์ ์ผ๋ก ์ธํ ๋ฐ์ดํฐ์ ํํธํ๋ฅผ ์ค์ฌ์ค.
'WEB STUDY > REACT' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
React. styled-components (0) | 2022.05.01 |
---|---|
220317 TIL - markdown ver. (0) | 2022.03.17 |
220316 [TIL] Today I Learned ๐ฏ React.js (0) | 2022.03.16 |
220315 [TIL] Today I Learned ๐ฏ React.js - (2) (0) | 2022.03.15 |
220315 [TIL] Today I Learned ๐ฏ React.js - (1) (0) | 2022.03.15 |