habit.jsx에서 PureComponent 해버리면, 업데이트가 되지 않을 것이다.
이렇게 업데이트 되지 않는 모습을 볼 수 있다.
이 이유는 purecomponent는 shallow 하게 prop안에 데이터가 변경되지않으면 렌더되지 않는다고 생각이 들기 때문이다. 참조값을 받기 때문에, 멤버변수가 전달되고 우리는 habit안에 있는 오브젝트 안에 있는 count 안의 데이터만 바뀌기 때문에 오브젝트가 변하는 것은 아니다. 그렇기 때문에 동일하다고 판단 되므로 render함수가 호출이 되지 않는다.
여기서 purecomponent를 사용하고 해결할 수 있는 방법은 2가지가 있다.
1. 우리가 전달할 때 변화하는 것을 따로 빼서 전달한다.
habit컴포넌트 기준으로 우리는 habit의 count가 변화된다. 이것을 따로 props로 빼서 전달한다.
habits.jsx
render() {
return (
<>
<HabitAddForm onAdd={this.handleAdd} />
<ul>
{this.props.habits.map((habit) => (
<Habit
key={habit.id}
habit={habit}
count={habit.count}
name={habit.name}
onIncrement={this.handleIncrement}
onDecrement={this.handleDecrement}
onDelete={this.handleDelete}
/>
))}
</ul>
<button className="habits-reset" onClick={this.props.onReset}>
Reset All
</button>
</>
);
}
}
habits.jsx 기준으로 habit 컴포넌트에서 props를 넘길 때 count와 name을 따로 지정해줘서 props 자체의 count와 name이 변경될 수 있게 만들어주면, habit 컴포넌트가 purecomponent여도 가능해진다.
하지만 이렇게 되면, props로 받아올 데이터가 너무 많아지고, 코드 자체가 엄청나게 복잡해진다.
그렇기에 다른 방법으로 purecomponent를 사용해야 한다.
2. app.jsx에서 id를 비교해주며 count 자체를 새로 생성해주는 형식으로 만들어준다.
app.jsx
class App extends Component {
state = {
habits: [
{ id: 1, name: "Reading", count: 0 },
{ id: 2, name: "Running", count: 0 },
{ id: 3, name: "Coding", count: 0 },
],
};
handleIncrement = (habit) => {
// state 오브젝트 안에 있는 count 를 증가한 뒤 state를 업데이트 해야 함
const habits = this.state.habits.map((item) => {
if (item.id === habit.id) {
return { ...habit, count: habit.count + 1 };
} else {
return item;
}
});
this.setState({ habits });
};
handleDecrement = (habit) => {
// state 오브젝트 안에 있는 count 를 증가한 뒤 state를 업데이트 해야 함
const habits = this.state.habits.map((item) => {
if (item.id === habit.id) {
const count = habit.count - 1;
return { ...habit, count: count < 0 ? 0 : count };
} else {
return item;
}
});
this.setState({ habits });
};
handleReset = () => {
const habits = this.state.habits.map((habit) => {
if (habit.count !== 0) {
return { ...habit, count: 0 };
} else {
return habit;
}
});
this.setState({ habits });
};
이렇게 handleIncrement와 decrement 는 item.id와 habit.id를 비교해주면서, 내가 선택한 습관과 item의 습관이 동일하다면
_1 해주거나 -1 해줄 수 있게 조건을 걸고, habit 배열을 복사해온 다음, 내가 변경해야 할 count 부분만 따로 변경해주면 props 자체 내에서 변경해주는 것이 된다.
reset 같은 경우에는 habit.count 자체를 0으로 만들면 되니까, 0이 아닐 시에만 count를 모두 0으로 만들어버리면 된다.
그리고 purecomponent가 가능한 navbar도 동일하게 purecomponent로 만들어준다.
habits.jsx 자체도 purecomponent로 만들어주어도 괜찮은데, habits.jsx 컴포넌트 자체가 사실 habit의 목록을 받아오기 때문에 어떤카운트가 변경되고 업데이트 되어도 결국엔 새로운 habit의 목록을 받기 때문에 어차피 purecomponent를 사용해도 어차피 habit도 계속 업데이트 되기 때문에 조금 불필요하다고 생각이 든다.
'React' 카테고리의 다른 글
react function 컴포넌트, memo 정리 (0) | 2022.09.09 |
---|---|
react lifecycle 함수 이해하기 (0) | 2022.09.08 |
react PureComponent 정리와 차이점 이해 (성능 분석) (0) | 2022.09.07 |
react reset 버튼 만들기 (0) | 2022.09.07 |
react input / add form 컴포넌트 만들기 (0) | 2022.09.07 |