React
는 기존 컴포넌트와 가상 컴포넌트를 비교해 변화를 감지하면 새로운 렌더링을 적용한다. 이 때문에 애니메이션을 적용할 때 문제가 발생했다. 조건이 변경될 때마다 fade in
이 한 번 적용되는 목적으로 애니메이션을 만들었지만, 최초 렌더링 시에만 동작하고, 이후 변화가 없었다. 확실히 기억하고자 재현한 코드를 기록한다.
테스트 코드는 다음과 같다.
CSS
.true {
width: 100px;
height: 100px;
background-color: red;
}
.false {
width: 100px;
height: 100px;
background-color: blue;
}
.fade-in {
animation: fadeIn 1s ease 0s 1 normal forwards;
}
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
JSX
const App = () => {
const [toggle, setToggle] = useState(true)
return (
<div>
<button type="button" onClick={() => setToggle((prev) => !prev)}>
Toggle
</button>
{ toggle ?
<div className="true fade-in" />
: <div className="false fade-in" /> }
</div>
)
}
처음 렌더링될 때는 fade-in
이 정상 동작하지만, 이후에는 버튼을 아무리 눌러도 애니메이션이 발생하지 않았다. id
를 다르게 주입해도 마찬가지였다. 태그명을 바꾸면 확실히 달라져 적용되겠지만, 내가 원하는 방향은 그게 아니었다.
여기서 key
가 생각났다. React
는 key
를 통해 컴포넌트를 명확하게 구분한다. 배열로 만든 컴포넌트에 key
를 주입하는 이유이기도 하다.
따라서 다음과 같이 수정한 후 문제를 해결했다.
JSX
const App = () => {
// (...)
return (
<div>
{/* ... */}
{ toggle ?
<div key="red" className="true fade-in" />
: <div key="blue" className="false fade-in" /> }
</div>
)
}
같은 key
값을 주게 되면 동일한 컴포넌트로 인식하므로, 유일한 값을 주입하는 것이 좋다.
재현 결과는 아래에서 확인할 수 있다.