필요할 때만 렌더 한다.
npx crate-create-app react-advanced
cd react-advanced
code . -r
App.js =>
import React from "react";
class Foo extends React.Component {
componentDidMount() {
console.log("Foo componentDidMount");
}
componentWillUnmount() {
console.log("Foo componentWillUnmount");
}
render() {
return <p>Foo</p>;
}
}
class App extends React.Component {
state = {
count: 0,
};
componentDidMount() {
setInterval(() => {
this.setState({ count: this.state.count + 1 });
}, 1000);
}
render() {
if (this.state.count % 2 === 0) {
return (
<div>
<Foo />
</div>
);
}
return (
<span>
<Foo />
</span>
);
}
}
export default App;
// >>> 같은 컴포넌트의 상위 엘리멘트, props, attribute, 인라인스타일 등이 다르면
//Foo도 다른 컴포넌트로 인식.
//=> 1초에 한번씩 Foo는 Didmount, unmount되면서 번갈아 계속 render됨
App.js =>
import React from "react";
class Foo extends React.Component {
componentDidMount() {
console.log("Foo componentDidMount", this.props.children);
}
componentWillUnmount() {
console.log("Foo componentWillUnmount");
}
static getDerivedStateFromProps(nextProps, prevProps) {
console.log("Foo getDerivedStateFromProps", nextProps, prevProps);
return {};
}
render() {
console.log("Foo render", this.props.children);
return <p>Foo</p>;
}
}
class App extends React.Component {
state = {
count: 0,
};
componentDidMount() {
setInterval(() => {
this.setState({ count: this.state.count + 1 });
}, 5000);
}
render() {
if (this.state.count % 2 === 0) {
return (
// 같은 key props를 지정해줌으로서 같은 컴포넌트로 인식
<ul>
<Foo key="2">second</Foo>
<Foo key="3">third</Foo>
</ul>
);
}
return (
<ul>
<Foo key="1">first</Foo>
<Foo key="2">second</Foo>
<Foo key="3">third</Foo>
</ul>
);
}
}
export default App;
App.js =>
import React from "react";
class Person extends React.Component {
shouldComponentUpdate(previousProps) {
for (const key in this.props) {
if (previousProps[key] !== this.props[key]) {
return true; // 새로 렌더
}
}
return false; // 같은것이니 렌더X
}
render() {
console.log("Person render");
const { name, age } = this.props;
return (
<div>
{name} / {age}
</div>
);
}
}
class App extends React.Component {
state = {
text: "",
persons: [
{ id: 1, name: "Mark", age: 39 },
{ id: 2, name: "Hanna", age: 28 },
],
};
render() {
const { text, persons } = this.state;
return (
<div>
<input type="text" value={text} onChange={this._change} />
<ul>
{persons.map((person) => {
return <Person {...person} key={person.id} />;
})}
</ul>
</div>
);
}
_change = (e) => {
this.setState({
...this,
text: e.target.value,
});
};
}
export default App;
App.js =>
class Person extends React.PureComponent {
/*shouldComponentUpdate(previousProps ) {
for (const key in this.props){
if(previousProps[key] !== this.props[key]) {
return true // 새로 렌더
}
}
return false // 같은것이니 렌더X
}*/
render () {
console.log('Person render');
const {name , age } = this.props
return (
<div>
{name} / {age }
</div>
)
}
}
class App extends React.Component {
state = {
text: "",
persons:[
{id: 1, name: 'Mark', age:39},
{id: 2, name: 'Hanna', age:28}
]
};
render() {
const {text, persons } = this.state;
return (<div>
<input type="text" value={text} onChange={this._change}/>
<ul>{persons.map(person => {
return <Person {...person} key={person.id} />
})}</ul>
</div>
)
}
_change = e => {
this.setState({
...this
text : e.target.value,
})
}
}
export default App;
App.js =>
import React from "react";
class Person extends React.PureComponent {
/*shouldComponentUpdate(previousProps ) {
for (const key in this.props){
if(previousProps[key] !== this.props[key]) {
return true // 새로 렌더
}
}
return false // 같은것이니 렌더X
}*/
render() {
console.log("Person render");
const { name, age } = this.props;
return (
<div>
{name} / {age}
</div>
);
}
}
class App extends React.Component {
state = {
text: "",
persons: [
{ id: 1, name: "Mark", age: 39 },
{ id: 2, name: "Hanna", age: 28 },
],
};
render() {
const { text, persons } = this.state;
return (
<div>
<input type="text" value={text} onChange={this._change} />
<ul>
{persons.map((person) => {
// return <Person {...person} key={person.id} />
// return <Person {...person} key={person.id} onClick={() => {}}/>
// onClick 의 props에 들어간 함수가 매번 새로 만들어지기 때문에 render가 반복된다.
// 이 경우 따로 메서드를 만들어 넣는게 좋다.
// ==> toPersonClick = () => {};
// ==> return <Person {...person} key={person.id} onClick={() => {}}/>
return (
<Person
{...person}
key={person.id}
onClick={this.toPersonClick}
/>
);
})}
</ul>
</div>
);
}
_change = (e) => {
this.setState({
...this,
text: e.target.value,
});
};
toPersonClick = () => {};
}
export default App;
App.js =>
import React from "react";
// 1. 함수 컴포넌트를 React.memo로 감싸서 실행
const Person = React.memo(({ name, age }) => {
console.log("Person render");
return (
<div>
{name} / {age}
</div>
);
});
// 2. useCallback의 사용
function App() {
const [state, setState] = React.useState({
text: "",
persons: [
{ id: 1, name: "Mark", age: 39 },
{ id: 2, name: "Hanna", age: 28 },
],
});
const toPersonClick = React.useCallback(() => {}, []);
// dependancy 리스트에 의해 처음에만 렌더됨.
const { text, persons } = state;
return (
<div>
<input type="text" value={text} onChange={change} />
<ul>
{persons.map((person) => {
// return <Person {...person} key={person.id} />
//return <Person {...person} key={person.id} onClick={() => {}}/>
// onClick 의 props에 들어간 함수가 매번 새로 만들어지기 때문에 render가 반복된다.
// 이 경우 따로 메서드를 만들어 넣는게 좋다.
// ==>
return <Person {...person} key={person.id} onClick={toPersonClick} />;
})}
</ul>
</div>
);
function change(e) {
setState({
...state,
text: e.target.value,
});
}
// onClick에서 toPersonClick함수가 계속 실행되어 재렌더된다.
// => useCallback 함수를 이용
// function toPersonClick() {}
}
export default App;