react native로 작업을 하던 중, TextInput 클릭 시 TextInput width가 줄어들고 cancel 버튼이 생기고 cancel 버튼을 누르면 다시 사라지는 헤더를 구현하고 싶었다.
☝️ 이것 처럼 !
처음에는 이렇게 작성하였다.
type InputProps = {
width: number;
isPress: boolean;
};
const SearchWrapper = styled.View`
flex-direction: row;
align-items: center;
width: 100%;
`;
const SearchContainer = styled.View<InputProps>`
flex-direction: row;
width: ${(props) =>
props.isPress ? props.width / 1.3 : props.width / 1.1}px;
background-color: ${(props) => props.theme.theme.formColor};
padding: 6px 10px;
border-radius: 10px;
`;
const SearchInput = styled.TextInput`
color: ${(props) => props.theme.theme.textColor};
width: 100%;
margin-left: 10px;
`;
function Search() {
const SearchBox = () => (
<SearchWrapper>
<SearchContainer width={width} isPress={isPress}>
<Ionicons name="search" size={24} color={theme.theme.darkGray} />
<SearchInput
placeholder="Search"
autoCapitalize="none"
returnKeyLabel="Search"
returnKeyType="search"
autoCorrect={false}
onChangeText={(text) => setValue("keyword", text)}
onSubmitEditing={handleSubmit(onValid)}
onFocus={() => setIsPress(!isPress)}
/>
</SearchContainer>
{isPress ? (
<CancelContainer
onPress={() => {
reset({ keyword: "" });
setIsPress(!isPress);
}}
>
<Text>Cancel</Text>
</CancelContainer>
) : null}
</SearchWrapper>
);
useEffect(() => {
navigation.setOptions({
headerTitle: SearchBox,
});
}, []);
}
이렇게 작성하니 console.log(isPress); 했을 때 isPress의 값은 토글되지만 css에는 변동이 없었다.
구글링을 하다가 useLayoutEffect를 사용한 케이스를 보게됐다 !
바로 적용해봤더니 해결 ~!
useLayoutEffect(() => {
navigation.setOptions({
headerTitle: SearchBox,
});
}, [isPress]);
렌더가 화면에 그려진 후 비동기적으로 실행
참고
useEffect를 사용하는 경우, DOM의 레이아웃 배치와 화면이 업데이트 된 후 이펙트 함수를 호출한다.
- 컴포넌트 렌더링
- 화면 update
- useEffect 실행
✅ 일부 상태를 즉시 발생할 필요가 없을 경우
✅ 페이지에 시각적으로 영향을 주지 않는 무언가를 동기화 할 경우
✅ 이벤트 핸들러를 설정하는 경우
✅ 모달 상자가 나타나거나 사라질 때 일부 상태를 재설정하는 경우
렌더링 후 화면이 업데이트 되기 전에 동기적으로 실행
참고
- 컴포넌트 렌더링
- useLayoutEffect 실행
- 화면 update
✅ 상태가 업데이트 될 때 요소가 깜박이는 경우
✅ DOM을 변경하려는 경우
이 둘의 가장 큰 차이점은 렌더링 시점에 있다.
✅ DOM에서 레이아웃을 읽고 동기적으로 리렌더링하는 경우
=> 보통의 경우에는 useEffect를 먼저 사용하되, 만약 사용자가 알아차리는 DOM 변경을 하게 될 경우(ex. 화면 깜빡임)는 useLayoutEffect를 써야겠다!
https://hyojin96.tistory.com/entry/%F0%9F%8D%80-useEffect-VS-useLayoutEffect-%F0%9F%8D%80
https://merrily-code.tistory.com/46
https://velog.io/@ziyoonee/useLayoutEffect