[react-native] Stack Navigation

    반응형
    이 글은 <처음 배우는 리액트 네이티브 (김범준, 한빛미디어)>를 읽고 이해한 바를 바탕으로 작성한 글입니다.
     

    GitHub - Alchemist85K/my-first-react-native: [한빛미디어] 처음 배우는 리액트 네이티브 소스 코드입니다.

    [한빛미디어] 처음 배우는 리액트 네이티브 소스 코드입니다. . Contribute to Alchemist85K/my-first-react-native development by creating an account on GitHub.

    github.com

     

    내비게이션을 만드는 방법은 책에서 설명하는 React Navigation Library를 이용하는 방법 말고도 React Native Navigation Library를 사용하는 방법도 있다.

    우선 책에서는 React Navigation Library를 사용하고 있기 때문에 React Navigation Library를 이용해서 내비게이션을 만드는 방법에 대해서 포스팅-!

     

    💡 내비게이션 종류와 구조

    리액트 내비게이션 라이브러리에서 지원하는 내비게이션의 종류는 스택stack 내비게이션, 탭tab 내비게이션, 드로어drawer 내비게이션 세 종류이다.

     

    내비게이션에는 NavigationContainer 컴포넌트, Navigator 컴포넌트, Screen 컴포넌트가 있다.

    • Screen 컴포넌트
      : 화면으로 사용되는 컴포넌트로 name 속성과 component 속성을 지정해주어야 한다.
      1. name 속성: 화면 이름
      2. componen 속성: 화면으로 사용될 컴포넌트를 전달한다. 이 컴포넌트들을 항상 navigation과 route가 props로 전달된다.
    • Navigator 컴포넌트
      : 화면을 관리하는 중간 관리자 역할로, 내비게이션을 구성하며, 여러 개의 Screen 컴포넌트를 자식 컴포넌트로 갖는다.
    • NavigationContainer 컴포넌트
      : 내비게이션의 계층 구조와 상태를 관리하는 컨테이너 역하을 하며, 내비게이션의 모든 구조를 감싸는 최상위 컴포넌트!

    책 참고했습니다!

     

    💡 리액트 네이티브 내비게이션 사용하기

    ✔️리액트 내비게이션 라이브러리 설치

    npm install --save @react-navigation/native

     

    ✔️사용하는 내비게이션의 종류에 따라 개별적으로 추가 라이브러리를 설치해야 함

    expo install react-native-gesture-handler react-native-reanimated react-native-screens react-native-safe-area-context @react-native-community/masked-view

    (추가 라이브러리는 책에서 설치하라는 걸 그대로 설치했다... 어떤 라이브러리인지 모르지만 일단 설치,,)

     


    💡 스택 내비게이션 기본 컴포넌트 만들기

    스택 내비게이션은 말그대로 스택으로 작동되는 내비게이션이다...!

     

    스택 내비게이션을 사용하기 위해서는 스택 내비게이션 활용에 필요한 라이브러리가 또오-!? 필요하다.

    npm install @react-navigation/stack

     

    ✅src/screens/Home.js

    import React from 'react';
    import { Button } from 'react-native';
    import styled from 'styled-components/native';
    
    const Container = styled.View`
        justify-content: center;
        align-items: center;
    `;
    
    const StyledText = styled.Text`
        font-size: 30px;
        margin-bottom: 10px;
    `;
    
    const Home = () => {
        return (
            <Container>
                <StyledText>Home</StyledText>
                <Button title='go to the list screen' />
            </Container>
    
        )
    }
    
    export default Home;
    
    /* src/screens/Home.js */

    Screen 컴포넌트로 Home 컴포넌트를 만들었다.

     

    ✅src/screens/List.js

    import React from 'react';
    import { Button } from 'react';
    import { initialWindowMetrics } from 'react-native-safe-area-context';
    import styled from 'styled-components/native';
    
    const Container = styled.View`
        flex: 1;
        justify-content: center;
        align-iems: center;
    `;
    
    const StyledText = styled.Text`
        font-size: 30px;
        margin-bottom:10px;
    `;
    
    const items = [
        { _id: 1, name: 'React Native' },
        { _id: 2, name: 'React Navigation' },
        { _id: 3, name: 'Eunbin' },
    
    ];
    
    const List = () => {
        const _onPress = item => {};
    
        return (
            <Container>
                <StyledText>List</StyledText>
                {items.map(item => (
                    <Button
                        key = {item.id}
                        title = {item.name}
                        onPress = {() => _onPress(item)}
                    />
                ))}
            </Container>
        );
    };
    
    export default List;
    
    /* scr/screens/List.js */

    Screen 컴포넌트로 List 컴포넌트를 만들었다.

     

    ✅src/screens/Item.js

    import React from 'react';
    import styled from 'styled-components/native';
    
    const Container = styled.View`
        flex: 1;
        justify-content: center;
        align-items: center;
    `;
    
    const StyledText = styled.Text`
        font-size: 30px;
        margin-bottom: 10px;
    `;
    
    const Item = () => {
        return (
            <Container>
                <StyleldText>Item</StyleldText>
            </Container>
        )
    };
    
    export default Item;
    
    /* src/screens/Item.js */

    Screen 컴포넌트로 Item 컴포넌트를 만들었다.

     

    ✅src/navigations/Stack.js

    import React from 'react';
    import { createStackNavigator } from '@react-navigation/stack';
    import Home from '../screens/Home';
    import List from '../screens/List';
    import Item from '../screens/Item';
    
    const Stack = createStackNavigator();
    
    const StackNavigation = () => {
        return (
            <Stack.Navigator>
                <Stack.Screen name='Home' component={Home} />
                <Stack.Screen name='List' component={List} />
                <Stack.Screen name='Item' component={Item} />
            </Stack.Navigator>  
        );
    };
    
    export default StackNavigation;
    
    /* src/navigations/Stack.js */

    createStackNavigator()함수를 이용해서 스택 내비게이션을 생성한다.

    스택 내비게이션에는 화면을 구성하는 Screen 컴포넌트와 Screen 컴포넌트를 관리하는 Navigator 컴포넌트가 있다.

    Navigator 컴포넌트안에 3개의 Screen 컴포넌트를 자식 컴포넌트로 두었다.

    Screen 컴포넌트들은 앞에서 만든 Home, List, Item 컴포넌트를 지정해주었다.

     

     

    ✅App.js

    import App from './src/App';
    
    export default App;
    
    /* App.js */

     

    ✅src/App.js

    import React from 'react';
    import { NavigationContainer } from '@react-navigation/native';
    import StackNavigation from './navigations/Stack';
    
    const App = () => {
        return (
            <NavigationContainer>
                <StackNavigation />
            </NavigationContainer>
        )
    }
    
    export default App;
    
    /* src/App.js */

    StackNavigation을 NavigationContainer 컴포넌트가 최상위 컴포넌트로서 감싸게 한다.

     

    아마 위에 나오는 "Home"은 screen 컴포넌트에서 이름 속성으로 지정해 준 'Home'이 표시되는 것 같다.

     

    ✔️ 내비게이션의 화면 순서를 변경하려면?

    위에서는 Navigator 컴포넌트의 첫번째 자식으로 'Home' 컴포넌트를 지정해주었기 때문에 첫화면으로 Home 스크린 컴포넌트가 표시된다.

     

    화면 순서를 변경하고 싶다면

    1. Navigator의 자식 컴포넌트들의 순서를 바꿔주면 된다.

    const Stack = createStackNavigator();
    
    const StackNavigation = () => {
        return (
            <Stack.Navigator>
                <Stack.Screen name='List' component={List} />
                <Stack.Screen name='Home' component={Home} />
                <Stack.Screen name='Item' component={Item} />
            </Stack.Navigator>  
        );
    };
    
    export default StackNavigation;
    
    /* src/navigations/Stack.js */

    이렇게 첫번째 자식을 List로 변경해주었다.

     

    2. 또는 Navigator 컴포넌트에서 initialRouteName속성으로 첫 화면을 직접 명시해주는 방법도 있다.

    const Stack = createStackNavigator();
    
    const StackNavigation = () => {
        return (
            <Stack.Navigator initialRouteName='List'>
                <Stack.Screen name='Home' component={Home} />
                <Stack.Screen name='List' component={List} />
                <Stack.Screen name='Item' component={Item} />
            </Stack.Navigator>  
        );
    };
    
    export default StackNavigation;
    
    /* src/navigations/Stack.js */

    그러면 이렇게 첫 화면이 List 스크린 컴포넌트로 바뀐다.

    (안드로이드 디폴트는 증말 안이쁘네,,,)

     

    💡 화면 이동하기

    Screen 컴포넌트의 component로 지정된 컴포넌트는 화면으로 이용되고 navigation(여기서는 StackNavigation)이 props로 전달된다.

    즉, 자식인 Home 컴포넌트에게 navigation이 props로 전달된다. 그러면 Home 컴포넌트는 받은 props인 navigation의 navigate함수에 이동하고자 하는 스크린 컴포넌트의 이름을 넘겨주면 화면 이동이 가능하다. 

     

    ✅ Home에서 List로 이동 (src/screens/Home.js)

    import React from 'react';
    import { Button } from 'react-native';
    import styled from 'styled-components/native';
    
    const Container = styled.View`
        justify-content: center;
        align-items: center;
    `;
    
    const StyledText = styled.Text`
        font-size: 30px;
        margin-bottom: 10px;
    `;
    
    const Home = ({navigation}) => {
        return (
            <Container>
                <StyledText>Home</StyledText>
                <Button 
                title='go to the list screen' 
                onPress = {() => navigation.navigate('List')} 
                />
            </Container>
    
        )
    }
    
    export default Home;
    
    /* src/screens/Home.js */

    navigation을 prop로 받고, navigation.navigate()함수에 'List'를 넘겨주었다. 

    이제 버튼을 누르면 List 스크린 컴포넌트가 표시될 것이다. 

     

    ✅ List에서 Item으로 이동 (src/screens/List.js)

    List에서 Item으로 이동할 때에는 Item 화면에 대한 정보도 함께 전달해보도로 하겠다.

    왜냐하면 지금처럼 이동하는 화면이 이전 화면의 상세 화면이라면(List -> Item), 상세 화면은 어떤 내용을 렌더링해야 하는지 전달받아야 할 것이다.

    이럴 때에는navigate()함수에 파라미터를 추가해서 전달할 수 있다.

    navigate()함수에 두번째 파라미턴에 객체를 전달하여 item 화면에 대한 정보도 함께 전달한다.

    import React from 'react';
    import { Button } from 'react-native';
    import styled from 'styled-components/native';
    
    const Container = styled.View`
        flex: 1;
        justify-content: center;
        align-items: center;
    `;
    
    const StyledText = styled.Text`
        font-size: 30px;
        margin-bottom:10px;
    `;
    
    const items = [
        { _id: 1, name: 'React Native' },
        { _id: 2, name: 'React Navigation' },
        { _id: 3, name: 'Eunbin' },
    
    ];
    
    const List = ({navigation}) => {
        const _onPress = item => {
            navigation.navigate('Item', {id: item._id, name: item.name})
        };
    
        return (
            <Container>
                <StyledText>List</StyledText>
                {items.map(item => (
                    <Button
                        key = {item.id}
                        title = {item.name}
                        onPress = {() => _onPress(item)}
                    />
                ))}
            </Container>
        );
    };
    
    export default List;
    
    /* scr/screens/List.js */

     

    navigation()함수의 두번째 파라미터에 {id: item._id, name: item.name}객체를 넘겨주었다. id는 item의 _id로, name은 item의 name으로!

    따라서 Item 화면으로 넘어갈 때 항목의 id와 name이 함께 전달된다.

     

    ✅ 넘겨받은 id와 name 확인하기

    전달된 내용은 컴포넌트의 props로 전달되는 route의 params를 통해 확인할 수 있다.

     

    const Item = ({route}) => {
        return (
            <Container>
                <StyledText>Item</StyledText>
                <StyledText>ID: {route.params.id}</StyledText>
                <StyledText>Name: {route.params.name}</StyledText>
            </Container>
        )
    };
    
    export default Item;
    
    /* src/screens/Item.js */

    이렇게{route.params.id}{route.params.name}을 같이 표시되게 하여 넘겨받은 정보를 확인하여 보겠다.

     

     

    💡 화면 배경색 수정하기

    navigator 컴포넌트의 screenOptions 속성에서 cardStyle을 이용하면 스택 내비게이션의 화면 배경색을 수정할 수 있다.

    이렇게하면 화면 컴포넌트들마다 따로따로 배경색을 지정해주지 않아도 모든 화면 전체에 적용되도록 할 수 있다.

    const StackNavigation = () => {
        return (
            <Stack.Navigator 
            initialRouteName='Home'
            screenOptions = {{ cardStyle: {backgroundColor: '#fffff'} }}>
                <Stack.Screen name='Home' component={Home} />
                <Stack.Screen name='List' component={List} />
                <Stack.Screen name='Item' component={Item} />
            </Stack.Navigator>  
        );
    };
    
    /* src/navigations/Stack.js */

    원래 배경색을 아무것도 지정해주지 않았을 때는 회색이었는데, cardStyle로 #ffffff(흰색)으로 배경색을 지정해주니까 흰색으로 배경색이 바뀌었다!

     

    💡 헤더 수정하기

    노란색 부분이 헤더!

    헤더는 뒤로 가기 버튼을 제공하고 타이틀을 통해 현재 화면이 어디인지 알려주는 역할을 한다.

     

    ✔️ 헤더 타이틀 수정하기

    1. screen 컴포넌트에서 name 속성값 변경해주기

    헤더의 타이틀은 Screen 컴포넌트의 name 속성이 기본값으로 표시된다. 이것을 변경하는 방법은 name 속성에서 원하는 title로 바꿔주면 된다.

    const StackNavigation = () => {
        return (
            <Stack.Navigator 
            initialRouteName='Home'
            screenOptions = {{ cardStyle: {backgroundColor: '#ffffff'} }}>
                <Stack.Screen name='Home' component={Home} />
                <Stack.Screen name='List' component={List} />
                <Stack.Screen name='Detail' component={Item} />
            </Stack.Navigator>  
        );
    };
    ...
    /* src/navigations/Stack.js */

    Item 스크린 컴포넌트의 name 속성을 'Detail'로 변경해보았다.

    그럼 이렇게 헤더 부분이 Item에서 Detail로 바뀌었음을 확인할 수 있다.

     

    const List = ({navigation}) => {
        const _onPress = item => {
            navigation.navigate('Detail', {id: item._id, name: item.name})
        };
    
        return (
        ...
        );
    };
    
    /* src/screens/List.js */

    하지만, 원래 item 스크린 컴포넌트의 name 속성을 사용하던 부분도 모두 바뀐 'Detail'로 일일히 바꾸어주어야한다는 단점이 있다.

     

    이런 단점을 피하기 위해서 name 속성에서 헤더 타이틀을 변경하는 방법 외에 다른 방법을 사용할 수 있다.

     

    2. headerTitle 속성 이용하기

    스크린 컴포넌트에서 name속성이 아니라 options속성에서 headerTitle에 값을 명시해주는 것이다.

    const StackNavigation = () => {
        return (
            <Stack.Navigator 
            initialRouteName='Home'
            screenOptions = {{ cardStyle: {backgroundColor: '#ffffff'} }}>
                <Stack.Screen name='Home' component={Home} />
                <Stack.Screen 
                    name='List' 
                    component={List}
                    options = {{ headerTitle: 'List Screen' }}
                    />
                <Stack.Screen name='Item' component={Item} />
            </Stack.Navigator>  
        );
    };
    
    export default StackNavigation;
    
    /* src/navigations/Stack.js */

    이렇게 List 스크린 컴포넌트에서 options속성에서 headerTitle값을 'List Screen'으로 지정해주었다.

    이렇게 List 화면의 헤더 타이틀이 'List Screen'으로 변경된다.

     

    ✔️ 헤더 스타일 수정하기

    헤더의 스타일의 속성은 헤더 배경색을 수정하는 headerStyle과 헤더의 타이틀 컴포넌트의 스타일을 수정하는 headerTitleStyle이 있다.

    const StackNavigation = () => {
        return (
            <Stack.Navigator 
            initialRouteName='Home'
            screenOptions = {{
                cardStyle: {backgroundColor: '#ffffff'},
                headerStyle: {
                    height: 110,
                    backgroundColor: '#FFD8CC',
                    borderBottomWidth: 1,
                    borderBottomColor: '#99154E',
                },
                headerTitleStyle: {color: '#000000', fontsize: 24},
                headerTitleAlign: 'center',
                }}
            >
         	...
        );
    };
    
    /* src/navagations/Stack.js */

    screenOptions 속성에서 headertStyleheaderTitleStyle, headerTitleAlign 속성들을 이용해서 헤더 부분을 스타일링하였다.

     

    ✔️ 헤더 타이틀 컴포넌트 변경하기

    헤더 타이틀에 단순한 문자열이 아닌 다른 것을 렌더링하고 싶다면, 컴포넌트를 렌더링하게 할 수 있다.

    const StackNavigation = () => {
        return (
            <Stack.Navigator 
            initialRouteName='Home'
            screenOptions = {{
                cardStyle: {backgroundColor: '#ffffff'},
                headerStyle: {
                    height: 110,
                    backgroundColor: '#FFD8CC',
                    borderBottomWidth: 1,
                    borderBottomColor: '#99154E',
                },
                headerTitleStyle: {color: '#000000', fontsize: 24},
                headerTitleAlign: 'center',
                headerTitle: ({style}) => (
                    <MaterialCommunityIcons name='react' style={style} />
                )
                }}
            >
        ...
        )
    }
    
    /* src/navigations/Stack.js */

    headerTitle 속성에 기본적으로 제공되는 vector-icons의 리액트 로고가 렌더링 되도록 하였다.

    headerTitle 함수의 파라미터로 전달되는 style은 headerTitle에 지정한 스타일과 동일하게 적용되도록 작성하였다.

    헤더 타이틀에 리액트 로고가 렌더링됨

     

    ✔️ 헤더의 버튼 수정하기

    헤더에 존재하는 버튼

    이렇게 헤더 왼쪽에는 이전 화면으로 이동하는 버튼이 존재한다.

    하지만, iOS와 안드로이드에서는 이 버튼이 표시되는 것에 차이가 있는데, iOS에서는 버튼의 타이틀을 보여주지만, 안드로이드에서는 버튼의 타이틀으 보여주지 않는다. 

    이것은 headerBackTitleVisible을 이용해서 버튼 타이틀의 렌더링 여부를 동일하게 설정할 수 있다.

    const StackNavigation = () => {
        return (
            <Stack.Navigator 
            initialRouteName='Home'
            screenOptions = {{
                cardStyle: {backgroundColor: '#ffffff'},
                headerStyle: {
                    height: 110,
                    backgroundColor: '#FFD8CC',
                    borderBottomWidth: 1,
                    borderBottomColor: '#99154E',
                },
                headerTitleStyle: {color: '#000000', fontsize: 24},
                headerTitleAlign: 'center',
                headerTitle: ({style}) => (
                    <MaterialCommunityIcons name='react' style={style} />
                ),
                headerBackTitleVisible: true,
                }}
            >
        ...
        )
    }
    /* src/navigations/Stack.js */

     

    screenOptions 속성에서 headerBackTitleVisible을 true로 설정하여 지금 내 안드로이드 에뮬레이터에서 뒤로가기 버튼의 title을 보이도록 설정해주었다.

    뒤로가기 버튼의 title이 표시된다.

    만약, 뒤로가기 버튼의 이름을 이전 화면의 이름이 아니라 내가 직접 지정한 이름이 나타나도록 하고 싶다면, headerBackTitle을 이용한다.

    const StackNavigation = () => {
        return (
            <Stack.Navigator 
            initialRouteName='Home'
            screenOptions = {{
                cardStyle: {backgroundColor: '#ffffff'},
                headerStyle: {
                    height: 110,
                    backgroundColor: '#FFD8CC',
                    borderBottomWidth: 1,
                    borderBottomColor: '#99154E',
                },
                headerTitleStyle: {color: '#000000', fontsize: 24},
                headerTitleAlign: 'center',
                headerTitle: ({style}) => (
                    <MaterialCommunityIcons name='react' style={style} />
                ),
                headerBackTitleVisible: true,
                headerBackTitle: 'Prev',
                }}
            >
        );
    };
    
    /* src/navigations/Stack.js */

     

    ✔️ 헤더의 버튼 스타일 수정하기

    버튼 스타일은 headerBackTitleStyle을 이용하여 지정할 수 있다.

    headerBackTitleSylte은 버튼 스타일'만' 지정가능하며, 버튼의 타이틀과 헤더 타이틀의 색을 동일하게 변경하려면 headerTintColor를 사용할 수 있다.

    headerTintColor에서 지정한 색은 버튼과 타이틀에 모두 적용되지만 headerTitleStyle과 headerBackTitleStyle보다는 우선순위가 낮다.

    const StackNavigation = () => {
        return (
            <Stack.Navigator 
            initialRouteName='Home'
            screenOptions = {{
                cardStyle: {backgroundColor: '#ffffff'},
                headerStyle: {
                    height: 110,
                    backgroundColor: '#FFD8CC',
                    borderBottomWidth: 1,
                    borderBottomColor: '#99154E',
                },
                headerTitleAlign: 'center',
                headerTitle: ({style}) => (
                    <MaterialCommunityIcons name='react' style={style} />
                ),
                headerBackTitleVisible: true,
                headerBackTitle: 'Prev',
                headerTitleStyle: {fontsize: 24}
                headerTintColor: '#e74c3c',
                }}
            >
           	...
        );
    };
    ...
    
    /* src/navigations/Stack.js */

    headerTintColor를 버튼과 헤더 타이틀에 모두 적용하기 위해 기존에 작성해두었던 headerBackTitle에서 지정해둔 컬러는 삭제하고 fontsize만 지정해두었다.

    버튼 타이틀과 헤더 타이틀이 모두 스타일링 되었다.

     

    ✔️ 헤더의 버튼 컴포넌트 변경하기

    iOS와 안드로이드에서 렌더링되는 뒤로가기 버튼의 아이콘은 다르다. 

    iOS에서는 < 이런 모양의 아이콘의 버튼이 렌더링되고,

    android에서는 이런 모양의 아이콘의 버튼이 렌더링된다.

     

    headerBackImage를 이용하면 뒤로가기 버튼 아이콘의 이미지를 변경할 수 있는데, headerBackImage에 컴포넌트를 반환하는 함수를 전달해서 두 플랫폼에서 동일한 버튼 이미지를 렌더링하도록 변경하여 보겠다.

    const StackNavigation = () => {
        return (
            <Stack.Navigator 
            initialRouteName='Home'
            screenOptions = {{
                ...
                headerTitleStyle: {fontsize: 24},
                headerTintColor: '#e74c3c',
                headerBackImage: ( {tintColor} ) => {
                    const style = {
                        marginRight: 5,
                        marginLeft: Platform.OS === 'ios' ? 11 : 0,
                    };
                    return (
                        <MaterialCommunityIcons
                            name = 'arrow-left-circle-outline'
                            size = {30}
                            color = {tintColor}
                            style = {style}   
                        />             
                    );
                },
                }}
            >
            ...
        );
    };
    ...
    
    /* src/navigations/Stack.js */

    headerBackImage의 함수에 tintColor값을 파라미터로 전달해서 아이콘의 색을 앞에서 지정했던 색으로 지정하고, 두 플랫폼의 버튼 위치를 동일하게 하기위해 marginLeft를 다르게 지정해주었다.

    버튼 이미지는 MaterialCommunityIcons 컴포넌트에서 arrow-left-circle-outline 이미지로 지정하였다.

    버튼 이미지 변경

     

    버튼 이미지가 아니라 버튼 자체를 전체적으로 스타일링하고 싶다면 headerLeft, headerRight에 컴포넌트를 반환하는 함수를 지정하여 왼쪽과 오른쪽에 원하는 컴포넌트를 렌더링시킬 수 있다.

    import React, { useLayoutEffect } from 'react';
    import styled from 'styled-components/native';
    import { MaterialCommunityIcons } from '@expo/vector-icons';
    
    const Container = styled.View`
        flex: 1;
        justify-content: center;
        align-items: center;
    `;
    
    const StyledText = styled.Text`
        font-size: 30px;
        margin-bottom: 10px;
    `;
    
    const Item = ({navigation, route}) => {
        useLayoutEffect(() => {
            navigation.setOptions({
                headerBackTitleVisible: false,
                headerTintColor: '#000000',
    
                headerLeft: ({ onPress, tintColor }) => {
                    return(
                        <MaterialCommunityIcons
                            name = 'arrow-left-circle-outline'
                            size = {30}
                            style = { { marginLeft: 11 }}
                            color = {tintColor}
                            onPress = {onPress}
                        />
                    );
                },
    
                headerRight: ({ tintColor }) => (
                    <MaterialCommunityIcons
                        name = 'home-variant'
                        size = {30}
                        style = {{ marginRight: 11}}
                        color = {tintColor}
                        onPress = {() => navigation.popToTop()}
                    />
                ),
            });
        }, []);
    
        return (
            <Container>
                <StyledText>Item</StyledText>
                <StyledText>ID: {route.params.id}</StyledText>
                <StyledText>Name: {route.params.name}</StyledText>
            </Container>
        )
    };
    
    export default Item;
    
    /* src/screens/Item.js */

    Item 화면에서 왼쪽 버튼과 오른쪽 버튼 컴포넌트를 각각 렌더링해주었다.

    useLayoutEffect Hook은  useEffect Hook과 거의 비슷하지만, 주요한 차이점은 컴포넌트가 업데이트된 직후 화면이 렌더링되기 전에 실행된다. 따라서 화면에 렌더링하기 전에 변경할 부분이 있거나 수치 등을 측정해야 하는 상황에서 많이 사용된다.

     

    왼쪽 버튼은 뒤로가기 버튼의 기능을 그대로 사용할 것이기 때문에 onPress를 그대로 사용해주었고,

    오른쪽 버튼은 모든 화면을 pop하고 첫 화면으로 돌아가는 기능을 사용할 것이기 때문에 onPress 이벤트에 popToTop 함수를 이용하였다.

    왼쪽 버튼과 오른쪽 버튼 컴포넌트 렌더링

     

    ✔️ 헤더 숨기기

    헤더를 감추기 위해 이용할 수 있는 설정은 headerModeheaderShown이다.

    1. headerMode
    : Navigator 컴포넌트의 속성으로 헤더를 렌더링하는 방법을 설정하는 속성이다.

    • float: 헤더가 상단에 유지되며 하나의 헤더를 사용 -> 무조건 헤더 사용
    • screen: 각 화면마다 헤더를 가지며 화면 벼경과 함께 나타나거나 사라짐 -> 화면에 따라서 있거나 없거나!
    • none: 헤더가 아예 렌더링되지 않음
    const StackNavigation = () => {
        return (
            <Stack.Navigator 
            initialRouteName='Home'
            screenOptions = {{
                ...
                headerMode: 'none',
                }}
            >
    	...
        );
    };
    
    /* scr/navigations/Stack.js */

    headerMode를 none으로 설정한 모습이다.

     

     

    2. headerShow

    : 화면 옵션으로, navigator 컴포넌트의 screenOptions에 설정하면 전체 화면의 헤더가 보이지 않게 설정할 수 있다.

    const StackNavigation = () => {
        return (
            <Stack.Navigator 
            ...
            >
                <Stack.Screen 
                    name='Home' 
                    component={Home}
                    options={{ headerShown: false}}
                    />
                <Stack.Screen 
                    name='List' 
                    component={List}
                    options = {{ headerTitle: 'List Screen' }, {headerShow: false}}
                    />
                <Stack.Screen name='Item' component={Item} />
            </Stack.Navigator>  
        );
    };
    
    export default StackNavigation;
    
    /* src/navigations/Stack.js */

    이렇게 스크린 컴포넌트 각각에 옵션을 주어서 header를 없앨 수도 있다.

    위에서는 Home과 List에만 옵션을 주어서 헤더를 숨겼기 때문에, Item 스크린에서만 header가 표시된다.

    Home과 List에서만 헤더가 사라짐

     

    반응형

    댓글