컴포넌트가 리렌더링되는 경우
- 컴포넌트의 상태(state)나 속성(props)이 변경되면, React는 이러한 변경 사항을 반영하기 위해 컴포넌트를 리렌더링한다.
- 부모 요소가 리렌더링될 때(컴포넌트의 상태나 속성이 변경되지 않더라도)
- 하위 상태(lower state)
index.jsx
import { useState } from 'react';
import { data } from '../../../../data';
import List from './List';
const LowerState = () => {
const [people, setPeople] = useState(data);
const [count, setCount] = useState(0);
return (
<section>
<button
className='btn'
onClick={() => setCount(count + 1)}
style={{ marginBottom: '1rem' }}
>
count {count}
</button>
<List people={people} />
</section>
);
};
export default LowerState;
List.jsx
import Person from './Person';
const List = ({ people }) => {
return (
<div>
{people.map((person) => {
return <Person key={person.id} {...person} />;
})}
</div>
);
};
export default List;
Person.jsx
import { useEffect } from 'react';
const Person = ({ name }) => {
console.log('render');
// useEffect(() => {
// console.log('unfortunately does not fix the issue');
// }, []);
return (
<div>
<h4>{name}</h4>
</div>
);
};
export default Person;
위의 경우 최초 렌더링시 'render'가 출력이 된다.
index.jsx에서 클릭이벤트(setCount)로 count의 상태 값이 변하므로 자식 요소인 Person.jsx도 리렌더링 된다.
index.jsx
import { useState } from 'react';
import { data } from '../../../../data';
import List from './List';
import Counter from './Counter';
const LowerState = () => {
const [people, setPeople] = useState(data);
return (
<section>
<Counter/>
<List people={people} />
</section>
);
};
export default LowerState;
Counter.jsx
import React, { useState } from 'react'
const Counter = () => {
const [count, setCount] = useState(0);
return (
<button
className='btn'
onClick={() => setCount(count + 1)}
style={{ marginBottom: '1rem' }}
>
count {count}
</button>
)
}
export default Counter
따로 상태를 관리하는 컴포넌트를 분리하여 하위 컴포넌트들이 리렌더링되는 것을 방지할 수 있다.
index.jsx
import { useState } from 'react';
import { data } from '../../../../data';
import List from './List';
const LowerStateChallenge = () => {
const [people, setPeople] = useState(data);
const [name, setName] = useState('');
const handleSubmit = (e) => {
e.preventDefault();
if (!name) {
alert('Please Provide Name Value');
return;
}
addPerson();
setName('');
};
const addPerson = () => {
const fakeId = Date.now();
const newPerson = { id: fakeId, name };
setPeople([...people, newPerson]);
};
return (
<section>
<form className='form' onSubmit={handleSubmit}>
<div className='form-row'>
<label htmlFor='name' className='form-label'>
name
</label>
<input
type='text'
name='name'
id='name'
className='form-input'
value={name}
onChange={(e) => setName(e.target.value)}
/>
</div>
<button className='btn btn-block' type='submit'>
submit
</button>
</form>
<List people={people} />
</section>
);
};
export default LowerStateChallenge;
List.jsx
import Person from './Person';
const List = ({ people }) => {
return (
<div>
{people.map((person) => {
return <Person key={person.id} {...person} />;
})}
</div>
);
};
export default List;
Person.jsx
const Person = ({ name }) => {
console.log('re-render')
return (
<div>
<h4>{name}</h4>
</div>
);
};
export default Person;
이름 인풋 값과 추가될 경우 리렌더링된다.