question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

useSafeAreaInsets all return 0 for values

See original GitHub issue

I am trying to fix an issue while using the tab navigator and/or Safe Area where my keyboardAvoidingView is covering the message input box on the chat screen when the keyboard is brought up. Not sure what the culprit is exactly, but I am pretty sure it’s the safeview padding on top and/or bottom, which I have learned are the “insets”. I am trying to use useSafeAreaInsets, but all the values return 0! (See in CustomKeyboardAvoidingView) I want to use those insets to add to the keyboardVerticalOffset param so the avoiding view works properly. I tried setting the keyboardVerticalOffset to a flat value, but it seems to be different depending on the device, aka the inset padding values would make sense. I like the style of the tab bar right now, so I’d like to keep it with an increased height and padding and font size, but maybe I am doing it wrong with react native navigation? Regardless, the insets should be returning a value.

I tried using the solution outlined in this issue: https://github.com/th3rdwave/react-native-safe-area-context/issues/54

Here is my App.js code recreating the issue:

import React, { Component, useEffect, useState } from 'react';
import { View, KeyboardAvoidingView, TextInput, Text, Platform, TouchableWithoutFeedback, Keyboard, ActivityIndicator, SafeAreaView, ScrollView, Button, StatusBar   } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import { createStackNavigator, useHeaderHeight } from '@react-navigation/stack';
import FontAwesome5 from 'react-native-vector-icons/FontAwesome5';
import { useSafeAreaInsets, useSafeAreaFrame } from 'react-native-safe-area-context';
import { Dimensions } from 'react-native';

const Stack = createStackNavigator();

function TicketStack() {
  return (
    <Stack.Navigator
    screenOptions={{
      headerStyle: { 
        backgroundColor: "dodgerblue",
        elevation: 0, // remove shadow on Android
        shadowOpacity: 0, // remove shadow on iOS
      },
      headerTintColor: "#fff",
      headerTitleStyle: {
        fontWeight: "900",
        fontSize: 26,
      },

    }}>
      <Stack.Screen name="Ticket">
        {(props) => <TicketScreen {...props} />}
      </Stack.Screen>
      <Stack.Screen name="Chat">
        {(props) => <ChatScreen {...props} />}
      </Stack.Screen>
    </Stack.Navigator>
  );
}

function HomeScreen() {
  return (
    <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
      <Text><FontAwesome5 name={"home"} size={20} color={"dodgerblue"} /> Home screen!</Text>
    </View>
  );
}

function TicketScreen(props){
  return (
    <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
      <Text>Ticket screen :)!</Text>
      <Button title="Go to Chat" onPress={() => props.navigation.navigate('Chat')} />
    </View>
  );
}

function CustomKeyboardAvoidingView({ children, style }) {
    const headerHeight = useHeaderHeight();
    const insets = useSafeAreaInsets();
    const [bottomPadding, setBottomPadding] = useState(insets.bottom)
    const [topPadding, setTopPadding] = useState(insets.top)
    // const frame = useSafeAreaFrame();
    // const windowHeight = Dimensions.get('window').height  
    useEffect(() => {
      setBottomPadding(insets.bottom)
      setTopPadding(insets.top)

      console.log("insets.top: " + topPadding)
      console.log("insets.bottom: " + bottomPadding)
    }, [insets.bottom, insets.top])


    // console.log("frame.height: " + frame.height)
    // console.log("windowHeight: " + windowHeight)
    // const safeAreaHeight = windowHeight - frame.height
    // console.log("safeAreaHeight: " + safeAreaHeight)
    // safeAreaHeight is too much, needs to just be bottom or top padding from safearea
    return (
        <KeyboardAvoidingView
            style={style}
            behavior={Platform.OS == "ios" ? "padding" : "height"}
            keyboardVerticalOffset={headerHeight + bottomPadding + StatusBar.currentHeight}
        >
            {children}
        </KeyboardAvoidingView>
    );
}

function ChatScreen(){
  return(

      <TouchableWithoutFeedback onPress={Keyboard.dismiss}>
        <CustomKeyboardAvoidingView style={{backgroundColor: "#fff", flex: 1, flexDirection: "column", justifyContent: "space-between" }}>
          <View style={{backgroundColor: "dodgerblue", paddingVertical: 15}}>
              <View style={{ margin: 10, marginBottom: 15}}>
                  <ActivityIndicator size="large" style={{marginBottom: 10}}/>
                  <Text>Waiting for more info here....</Text>
              </View>
          </View>

          <ScrollView style={{backgroundColor: "tomato", paddingVertical: 15}}>
              <Text>Chat messages</Text>
              <Text>Chat messages</Text>
              <Text>Chat messages</Text>
              <Text>Chat messages</Text>
              <Text>Chat messages</Text>
              <Text>Chat messages</Text>
              <Text>Chat messages</Text>
              <Text>Chat messages</Text>
              <Text>Chat messages</Text>
              <Text>Chat messages</Text>
              <Text>Chat messages</Text>
              <Text>Chat messages</Text>
              <Text>Chat messages</Text>
              <Text>Chat messages</Text>
              <Text>Chat messages</Text>
              <Text>Chat messages</Text>
              <Text>Chat messages</Text>
              <Text>Chat messages</Text>
              <Text>Chat messages</Text>
              <Text>Chat messages</Text>
              <Text>Chat messages</Text>
              <Text>Chat messages</Text>
              <Text>Chat messages</Text>
          </ScrollView>
          
          <View style={{backgroundColor: "yellow", paddingVertical: 15}}>
              <TextInput placeholder="Type your message here..." />
          </View>
        </CustomKeyboardAvoidingView>
      </TouchableWithoutFeedback>

  )
}

const Tab = createBottomTabNavigator();

// TODO:
// - removing safeareaview makes tabs squished and icon nearly invisible, but chat message input fields avoids keyboard properly (squished can be fixed by removing tabBarOptions)
// - having safeareaview makes tabs look good, but chat message input field is hidden by keyboard
// - safeareainsets? why are they 0?
// - subtract height of safe area from full screen height to get the padding?
export default class App extends Component {
  render(){
    return (
  
        <NavigationContainer>
          <Tab.Navigator
            screenOptions={({ route }) => ({
              tabBarIcon: ({ color, size }) => {
                let iconName;

                if (route.name === 'Home') {
                  iconName = 'home';
                } else if (route.name === 'Ticket') {
                  iconName = 'question';
                }
                return <FontAwesome5 name={iconName} size={size} color={color} />;
              },
            })}
            tabBarOptions={{
              style: {
                height: 70
              }, 
              activeTintColor: "#fff",
              inactiveTintColor: "dodgerblue",
              inactiveBackgroundColor: "#fff",
              activeBackgroundColor: "dodgerblue",                               
              tabStyle: {
                paddingTop: 10,
                paddingBottom: 10
              },
              labelStyle: {
                fontSize: 14
              },
            }}>
            <Tab.Screen name="Home">
              {(props) => <HomeScreen {...props} />}
            </Tab.Screen>
            <Tab.Screen name="Ticket">
              {(props) => <TicketStack {...props} />}
            </Tab.Screen>
          </Tab.Navigator>
        </NavigationContainer>
    
    );
  }
}

package.json

{
  "name": "ReactNativeTest",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "android": "react-native run-android",
    "ios": "react-native run-ios",
    "start": "react-native start",
    "test": "jest",
    "lint": "eslint ."
  },
  "dependencies": {
    "@react-native-community/masked-view": "^0.1.10",
    "@react-navigation/bottom-tabs": "^5.9.2",
    "@react-navigation/native": "^5.7.6",
    "@react-navigation/stack": "^5.9.3",
    "react": "16.13.1",
    "react-native": "0.63.3",
    "react-native-gesture-handler": "^1.8.0",
    "react-native-reanimated": "^1.13.1",
    "react-native-safe-area-context": "^3.1.8",
    "react-native-screens": "^2.11.0",
    "react-native-vector-icons": "^7.1.0"
  },
  "devDependencies": {
    "@babel/core": "7.11.6",
    "@babel/runtime": "7.11.2",
    "@react-native-community/eslint-config": "1.1.0",
    "babel-jest": "25.5.1",
    "eslint": "6.8.0",
    "jest": "25.5.4",
    "metro-react-native-babel-preset": "0.59.0",
    "react-test-renderer": "16.13.1"
  },
  "jest": {
    "preset": "react-native"
  }
}

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:12

github_iconTop GitHub Comments

19reactions
Seamus1989commented, Mar 16, 2021

still getting this despite use of <SafeAreaProvider />

8reactions
kaushil111commented, Oct 19, 2020

Same for me. Looking into this

Read more comments on GitHub >

github_iconTop Results From Across the Web

SafeAreaContext
You use the useSafeAreaInsets hook to get the insets in the form of { top: ... to inject values based on the device...
Read more >
Supporting safe areas
While React Navigation handles safe areas for the built-in UI elements by default, your own content also needs to handle it to ensure...
Read more >
Problem when testing a component with react-native-safe- ...
Provider> ); }, useSafeAreaInsets: jest.fn, // add more hooks if needed ... { const inset = { top: 0, right: 0, bottom: 0,...
Read more >
react-native-safe-area-context#useSafeAreaInsets
function Transaction(props) { const insets = useSafeAreaInsets(); return <_Transaction ... scrollIndex : 0 } if(range == "all"){ const calcedIndex ...
Read more >
react-native-safe-area-context
4.0.0+, 0.64.0+ ... these values will be provided to descendent consumers. ... const insets = useSafeAreaInsets(); return <View style={{ ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found