애증의 RN... 스타일링 하는 게 React랑 많이 달라서 어렵다... 누가 React 할 줄 알면 러닝커브 낮대... 아무튼 각설하고 React Native에서 flex gap을 편하게 쓰는 방법을 생각해보았고, 이를 공유하고자 한다.
스타일링을 할 때면, display: flex
를 참 많이 쓴다. 난 거의 모든 컴포넌트를 flexing하게 꾸민다. 위 예시와 함께 이야기 해보자.
대충, 위와 같이 생긴 profile card ui를 개발해야 한다고 하면 프로필 이미지, 이름, 한줄 소개, sns 목록들 요소를 각각 만들어서 profile card container에 넣어주는 것이 일반적이다. 각 요소들의 간격이 15px이라면 profile card container의 css는 대략 아래같이 생겼을 것이다.
display: flex;
flex-direction: column;
gap: 15px;
근데 문제는 React Native에서는 gap
property가 동작하지 않는다. 🤯 (emotion의 문제인지 진짜 RN에서 안되는 건지는 모르겠다) 그래서 이와 관련해서 best practice를 찾아보았는데 보통은 flex container에 들어가는 자식에 margin 혹은 padding을 붙여주더라...
그치만 이는 불편한 방법이라고 생각됐다. 컴포넌트 만들 때마다 하나하나씩 쪼개서 margin 혹은 padding을 붙이면, 재사용하기도 좋지 않고, 무엇보다 의미상 어울리지도 않는다!
props로 gap을 받는 View를 만들거다. 그리고 children으로 넘어오는 요소 하나하나에 margin을 붙여주도록 하자. 그럼 아래와 같다.
import styled from '@emotion/native';
import {View} from 'react-native';
export interface FlexViewProps {
children: React.ReactNode;
gapHorizental?: number;
gapVertical?: number;
}
export const FlexViewStyled = styled.View<FlexViewProps>`
display: flex;
margin: ${props =>
`-${(props.gapVertical || 0) / 2}px -${(props.gapHorizental || 0) / 2}px`};
`;
const FlexView = (props: FlexViewProps) => {
return (
<FlexViewStyled {...props}>
{Object.values(props.children || {})?.map((item, idx) => (
<View
key={idx}
style={{
marginTop: (props.gapVertical || 0) / 2,
marginBottom: (props.gapVertical || 0) / 2,
marginRight: (props.gapHorizental || 0) / 2,
marginLeft: (props.gapHorizental || 0) / 2,
}}>
{item}
</View>
))}
</FlexViewStyled>
);
};
export default FlexView;
코드가 간단해서 길게 설명할 것은 없고, props로 받는 gap에 맞춰 margin으로 간격을 조정해주는 거다. 아래 그리는 부분을 보면 children 하나하나에 View를 감싸주는 것을 볼 수 있다.
이제 FlexView 컴포넌트를 사용해줄 때 <FlexView gapHorizental={20}>
와 같이 사용해주면 된다! 그럼 아래와 같이 아름답게 gap이 잘 설정된 것을 볼 수 있다. 🥺
굿 아이디어!