[TIL] React - setState / CSS - vertical align center
[TIL]
React
setState
비동기 setState
어제 알아본 setState 비동기를 예상치 못하게 만나서 해결하게 되었다!
const [postTodo, setPostTodo] = useState({
todoText: props.isTodoEdit ? props.editTodo.todoText : "",
todoDone: false,
tempId: null,
});
처음 postTodo useState를 이용하여 state 선언을 할 때, props.editTodo.todoText를 set 해주었는데, postTodo를 사용할 때에는 props.editTodo.todoText 값이 할당되어 있지 않아서 왜 그런가 했었다.
setState는 비동기이기 때문에 값이 set이 될 때 나머지 코드도 이미 다 실행이 되기 때문에 render시에 업데이트 된 값(props.editTodo.todoText)을 볼 수 없었던 것이다.
그래서 나는 useEffect를 사용해서 state set을 해주기로 하였다.
useEffect를 이용해서 render가 되었을 때, props.editTodo의 값이 바뀌면 set을 하도록 한 것이다.
useEffect(() => {
setPostTodo({
todoText: props.isTodoEdit ? props.editTodo.todoText : "",
todoDone: false,
tempId: null,
});
}, [props.editTodo]);
그러나, 이 코드 또한 문제점이 있다.
useEffect의 dependency에 추가가 권고되는 변수들이 props.editTodo 이 외에도 props.isTodoEdit가 있는데, 이를 추가하면 too much render 가 된다..
functional update
그래서 알아보니 추가 dependency를 추가하지 않고, 함수형 업데이트를 사용해서 추가 변수들을 쓰지 않아도 되었다.
useEffect(() => {
// dependency 추가하지 않고, functional update 사용
setPostTodo((todo) => {
return { ...todo, todoText: props.editTodo.todoText };
});
}, [props.editTodo]);
이처럼 setState를 전 상태를 전달해서 그를 업데이트 하는 식으로 함수형으로 set을 하면 추가 dependency가 필요하지 않게 된다.
가독성 또한 좋으며 이전 state의 값을 이용하는 것이므로 좀 더 안전할 수 있겠다.
CSS 관련
수직 가운데 정렬
세로 가운데 정렬, 수직 가운데 정렬은 css를 사용하면 항상 어떻게 해야할지 바로바로 생각이 안나는 것 같다.
그래서 찾아보기도 했고, 찾아본 방법과 내가 나름 생각해낸 방법을 적어두어야 겠다.
1. line-height 이용
2. padding 이용
3. display table 이용
4. pseudo selector 이용
-
line-height 쓰기
가장 간단한 방법이고 직관적인 방법이라고 생각한다.
나는 거의 line-height를 즐겨쓰게 되는 것 같다
하지만, 이것은 정적인 웹에서만 해당이 된다는 것.
만약 가운데에 두고 싶은 text가 개행이 되거나 요소의 height가 달라지면 이 방법도 통하지 않게 된다.
line-height를 특정 px로 고정시켜서 사용하는 것이기 때문에 이 설정 px과 달라지면 정중앙으로 오지 않는다.
(text의 높이를 건드리는 것이므로 완전 text가 완전 넘어가버린다.) -
padding 이용
그래서 text의 양이 일정하지 않다면, height값을 빼고 padding을 넣으면 가운데로 보낼 수 있다.
-
display table 이용
찾아보면서 배운 것인데, 부모 요소에 display에 table을 지정하고, 가운데로 보내고 싶은 자식 요소들의 display를 table-cell로 설정하여 수직 가운데 정렬이 가능해진다.
[참고 및 출처] https://oursmalljoy.com/css-%EA%B8%80%EC%9E%90-%EC%88%98%EC%A7%81-%EA%B0%80%EC%9A%B4%EB%8D%B0-%EC%A0%95%EB%A0%AC-text-vertical-align/
-
pseudo selector 이용
나는 이렇게 구현해보았다.
사실 위의 상황과 많이 다를 수는 있으나 이런 방법으로도 구현할 수 있을 것 같다.
가상 선택자를 이용해서 absolute로 위치를 지정하고 content에 text를 쓰는 방법을 사용했다..row { display: flex; justify-content: space-between; align-items: center; margin: 4px auto; color: #fff; background: linear-gradient( 90deg, rgba(255, 118, 20, 1) 0%, rgba(255, 84, 17, 1) 100% ); padding: 16px; border-radius: 5px; width: 90%; } .complete { text-decoration: line-through; position: relative; } .complete::after { content: "COMPLETE!"; background-color: transparent; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); letter-spacing: 10px; font-size: 17px; font-weight: bold; color: black; opacity: 1; pointer-events: none; } .complete::before { content: ""; background-color: rgba(255, 255, 255, 0.5); position: absolute; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; }
그러니까, 가운데로 보낼 요소를 psuedo selector로 생성하는 것이다.
그 안의 content에 넣고 싶은 text를 넣고, pseudo selector를 absolute로 두어서 옮기면 된다!
element { top: 50%; left: 50%; transform: translate(-50%, -50%); }
이렇게 가운데로 보내면 된다. (수직 뿐만 아니라 좌우도 가운데)
나는 배경 색은 따로 가져가고 싶었기 때문에 pseudo selector를 하나 더 추가할 수 밖에 없었다.
따라서 이러한 방법을 통해서 내가 수직 가운데로 가기로 원하는 요소 (text)를 높이에 상관없이 가운데 정렬할 수 있었다.
댓글남기기