Closed James2516 closed 6 years ago
You can access the header height like this
import { Header } from 'react-navigation';
Header.HEIGHT;
I am getting this warning now. Seems like the approved method will fail soon.
Header.HEIGHT is deprecated and will be removed before react-navigation comes out of beta.
Any other way to get height of StackNavigator header?
So far I've been following hard-coded values here to avoid the warning from react navigation https://stackoverflow.com/questions/45698607/programmatically-retrieve-header-component-height-react-native
That's a good question, @kaiyuanneo. We've made some changes because the header wasn't working correctly in landscape and now the iPhoneX changes things.
@brentvatne added the deprecation warning - could you add any insight on how we could handle this question?
Once we determine that we should update the docs in some way
Also wondering what the 'correct' method is now for getting the height of the header.
I'm using Header.HEIGHT
in order to set this value as the width of my custom header button, i.e. to make my custom header button square, since it will automatically fill the full height of the header and I want it to always be a consistent 1:1 square aspect ratio.
@spencercarli - Header.HEIGHT
was initially removed when @davepack landed SafeAreaView
because the height is dynamic depending on orientation and Header.HEIGHT
is a constant. I added it back because I didn't want to outright break apps without a deprecation warning well in advance. We need a solution that lets components subscribe to the get the current header height and also subscribe to changes, until then we can leave Header.HEIGHT
as in. Open for ideas for how to solve this.
@brentvatne you mentioned that the height of the header is dynamic depending on orientation - does it also depend on the height of the status bar? I was looking into solutions for getting the current height of the status bar yesterday and saw that on iPhone X the behaviour of the status bar is different; it appears that it always has a height of 44pt, while on other iOS devices it has a height of 20pt by default, which can increase to 40pt (not 44pt), e.g. during a phone call.
@jordanmkoncz I believe so
@brentvatne Why don't you still export appBarHeight ?
@brentvatne What about adding a property onContainerLayout for the header nav props? Seems this might be fairly simple since React Native provides onLayout on all views, so it would just be a matter of passing the provided callback to the top-level View container of the header.
This seems to be needed for our app b/c KeyboardAvoidingView needs to know the top offset of the view, which is at the bottom of the StackNavigator. So I don't yet see how we can use react-navigation with a KeyboardAvoidingView, which is quite a strong limitation.
This is working for me...
import {
Dimensions,
KeyboardAvoidingView,
View,
} from 'react-native';
import React, { Component } from 'react';
import PropTypes from 'prop-types';
const { height: fullHeight } = Dimensions.get('window');
export default class LayoutView extends Component {
static propTypes = {
children: PropTypes.node.isRequired,
}
state = {
offset: 0,
}
onLayout = ({
nativeEvent: { layout: { height } },
}) => {
const offset = fullHeight - height;
this.setState({ offset });
}
render = () => (
<View style={{ flex: 1 }} onLayout={this.onLayout}>
<KeyboardAvoidingView
style={{ flex: 1 }}}
behavior="padding"
keyboardVerticalOffset={this.state.offset}
>
{this.props.children}
</KeyboardAvoidingView>
</View>
)
}
@jordanmkoncz - yup, and status bar matters too!
@elliotfleming - seems reasonable.
I left Header.HEIGHT
exposed until we have a better solution. please create a RFC if you care about solving this problem
my way:
navigationOptions:({navigation})=>{
return{
headerStyle:{marginTop:-30}
}
}`
These are the helpers that I use:
import { Dimensions, DeviceInfo, Platform } from 'react-native';
import { Header } from 'react-navigation';
export const LANDSCAPE = 'landscape';
export const PORTRAIT = 'portrait';
export const getHeaderHeight = () => {
let height;
const orientation = getOrientation();
height = getHeaderSafeAreaHeight();
height += DeviceInfo.isIPhoneX_deprecated && orientation === PORTRAIT ? 24 : 0;
return height;
};
// This does not include the new bar area in the iPhone X, so I use this when I need a custom headerTitle component
export const getHeaderSafeAreaHeight = () => {
const orientation = getOrientation();
if (Platform.OS === 'ios' && orientation === LANDSCAPE && !Platform.isPad) {
return 32;
}
return Header.HEIGHT;
};
export const getOrientation = () => {
const { width, height } = Dimensions.get('window');
return width > height ? LANDSCAPE : PORTRAIT;
};
Header.height is not accessible via react-navigation. Any update on this?
@Raunak-Agrawal just import as below
import { Header } from 'react-navigation-stack';
console.log(Header.HEIGHT)
Have you tried what you posted @tylerg509
It's been removed in react-navigation-stack
'Header.HEIGHT' is depreciated in v2
You can now use the 'useHeaderHeight' hook or 'HeaderHeightContext'
import { useHeaderHeight } from 'react-navigation-stack';
const headerHeight = useHeaderHeight();
console.warn(headerHeight)
Using useHeaderHeight
in the render()
function of a react-native Component is giving me the following error: "Invariant Violation: Invalid hook call. Hooks can only be called inside of the body of a function component."
What could I be doing wrong? It's in the render function.
Using
useHeaderHeight
in therender()
function of a react-native Component is giving me the following error: "Invariant Violation: Invalid hook call. Hooks can only be called inside of the body of a function component." What could I be doing wrong? It's in the render function.
You need to write functional components or HOC, you cannot use hooks in class components.
From the documentation: use hook for functional components to get header's height (please be sure you call useHeaderHeight
in body of your functional component and not inside of callbacks etc)
import { useHeaderHeight } from '@react-navigation/stack';
const headerHeight = useHeaderHeight();
or you can use HeaderHeightContext with React's Context API
import { HeaderHeightContext } from '@react-navigation/stack';
<HeaderHeightContext.Consumer>
{headerHeight => (
/* render something */
)}
</HeaderHeightContext.Consumer>
I have lot of trouble using useHeaderHeight()! It causes some UI regressions as the height suddenly change for nothing in particular. It also takes time to be calculate the right height so I can see the content of my screen move down after a quick time on my screen
I decided to keep the Header.HEIGHT constant for now
I have the same problem as @mi-mazouz, header height updating during render with a jerk in the UI. My header is transparent.
This is working for me...
import { Dimensions, KeyboardAvoidingView, View, } from 'react-native'; import React, { Component } from 'react'; import PropTypes from 'prop-types'; const { height: fullHeight } = Dimensions.get('window'); export default class LayoutView extends Component { static propTypes = { children: PropTypes.node.isRequired, } state = { offset: 0, } onLayout = ({ nativeEvent: { layout: { height } }, }) => { const offset = fullHeight - height; this.setState({ offset }); } render = () => ( <View style={{ flex: 1 }} onLayout={this.onLayout}> <KeyboardAvoidingView style={{ flex: 1 }}} behavior="padding" keyboardVerticalOffset={this.state.offset} > {this.props.children} </KeyboardAvoidingView> </View> ) }
@elliotfleming Will that work with a transparent header? (https://reactnavigation.org/docs/stack-navigator/#headerbackground) It seems not because a transparent header don't have height, right?
Take note, don't ask me to use HeaderHeightContext
nor useHeaderHeight
, they're raising an error on my Next.js app because that app and my mobile app share some components. https://github.com/expo/expo-cli/issues/1782
Using
useHeaderHeight
in therender()
function of a react-native Component is giving me the following error: "Invariant Violation: Invalid hook call. Hooks can only be called inside of the body of a function component." What could I be doing wrong? It's in the render function.You need to write functional components or HOC, you cannot use hooks in class components.
how can i get header height in class component i am using React navigation v5 help me @sharifhh
Using
useHeaderHeight
in therender()
function of a react-native Component is giving me the following error: "Invariant Violation: Invalid hook call. Hooks can only be called inside of the body of a function component." What could I be doing wrong? It's in the render function.You need to write functional components or HOC, you cannot use hooks in class components.
how can i get header height in class component i am using React navigation v5 help me @sharifhh
@kdpadhiyar
export const withHeight = (Component) => {
const height = useHeaderHeight();
return <Component height={height} />
}
Class Test ....
export default withHeight(Test);
you can see the height in Test component as this.props.height
😄
Same problem as @mi-mazouz and @PositronicBrain
During first render, I receive 2 difference value with useCurrentHeight
making a flicker.
The first one is wrong, and the second is the right one.
I'm using headerTransparent too
@sharifhh thank you so much for help.
I get this error when I try to use useHeaderHeight()
:
Error: Couldn't find the header height. Are you inside a screen in Stack?
Code:
//...
import {
createStackNavigator,
useHeaderHeight
} from '@react-navigation/stack';
//...
const AppStack = createStackNavigator();
const AppStackNavigation = () => {
const headerHeight = useHeaderHeight(); // <-- ERROR
console.log(headerHeight);
render (
//...
)
}
How to use this in class component?
You can use this in a class component by wrapping your render contents in a 'HeaderHeightContext.Consumer'
import {HeaderHeightContext} from '@react-navigation/stack';
render = () => {
return (
<HeaderHeightContext.Consumer>
{(headerHeight: any) => {
return (
<View>
<Text>Some Text</Text>
</View>
);
}}
</HeaderHeightContext.Consumer>
);
};
I get this error when I try to use
useHeaderHeight()
:Error: Couldn't find the header height. Are you inside a screen in Stack?
Code:
//... import { createStackNavigator, useHeaderHeight } from '@react-navigation/stack'; //... const AppStack = createStackNavigator(); const AppStackNavigation = () => { const headerHeight = useHeaderHeight(); // <-- ERROR console.log(headerHeight); render ( //... ) }
Does anyone have a solution to this? I'm getting the same error.
Is this in a React Native Class
component or a Function
component?
Thanks for the quick reply! Function
component.
I don't see any reason why you would receive an error there. I tried it in my app and it works as expected, no errors. What version of React Navigation stack are you using?
The version I am on is "@react-navigation/stack": "^5.7.1",
I was using createNativeStackNavigator
instead of createStackNavigator
, my bad! Otherwise it works as expected. Thanks @neclamis1285.
Awesome. Glad you got it working.
how to add more height to current height?
@lyseiha Have you tried the suggestions in #5936 and #283?
How would you get the header height, ie. use useHeaderHeight
or HeaderHeightContext
in a plain helper function? Since it is neither a "function component" nor within a class component
If I am understanding your question correctly, you could pass the header height from your function/class component to your utility function.
import {HeaderHeightContext} from '@react-navigation/stack';
export default class MyClassComponent extends Component<Props, State> {
static contextType = HeaderHeightContext;
const {headerHeight} = this.context;
console.log('HEADER HEIGHT: ' + Utils.doSomethingWithHeaderHeight(headerHeight));
render = () => {
<View style="{{height: headerHeight}}">
</View>
};
}
export const Utils = {
doSomethingWithHeaderHeight: (headerHeight) => {
return headerHeight + 10;
}
};
@neclamis1285 Just Wanted To Know Why You Are Increasing The Value By 10 In The Utility Function ?
I get this error when I try to use
useHeaderHeight()
:Error: Couldn't find the header height. Are you inside a screen in Stack?
Code://... import { createStackNavigator, useHeaderHeight } from '@react-navigation/stack'; //... const AppStack = createStackNavigator(); const AppStackNavigation = () => { const headerHeight = useHeaderHeight(); // <-- ERROR console.log(headerHeight); render ( //... ) }
Does anyone have a solution to this? I'm getting the same error.
I get this error when I try to use
useHeaderHeight()
:Error: Couldn't find the header height. Are you inside a screen in Stack?
Code://... import { createStackNavigator, useHeaderHeight } from '@react-navigation/stack'; //... const AppStack = createStackNavigator(); const AppStackNavigation = () => { const headerHeight = useHeaderHeight(); // <-- ERROR console.log(headerHeight); render ( //... ) }
Does anyone have a solution to this? I'm getting the same error.
function headerHeight() { const height = useHeaderHeight(); return height } const height = headerHeight();
Check this solution: link
You just need to update your import, That's it !
React navigation V6
import { useHeaderHeight } from '@react-navigation/elements'; const headerHeight = useHeaderHeight(); React navigation V5
import { useHeaderHeight } from '@react-navigation/stack'; const headerHeight = useHeaderHeight(); or with React Context's API (not recommended)
React navigation V4
import { Header } from 'react-navigation-stack'; const headerHeight = Header.HEIGHT; React navigation V2-V3
import { Header } from 'react-navigation'; const headerHeight = Header.HEIGHT;
Hey! This issue is closed and isn't watched by the core team. You are welcome to discuss the issue with others in this thread, but if you think this issue is still valid and needs to be tracked, please open a new issue with a repro.
@Kiran-infostretch I am still getting the same error some of the others are getting when trying to use useHeaderHeight()
Error: Couldn't find the header height. Are you inside a screen in a navigator with a header?
Has anyone else managed to figure this out? Any additional information would be greatly appreciated! "@react-navigation/elements": "^1.2.1",
Hey! This issue is closed and isn't watched by the core team. You are welcome to discuss the issue with others in this thread, but if you think this issue is still valid and needs to be tracked, please open a new issue with a repro.
Hey! This issue is closed and isn't watched by the core team. You are welcome to discuss the issue with others in this thread, but if you think this issue is still valid and needs to be tracked, please open a new issue with a repro.
I get this error when I try to use
useHeaderHeight()
:Error: Couldn't find the header height. Are you inside a screen in Stack?
Code:
//... import { createStackNavigator, useHeaderHeight } from '@react-navigation/stack'; //... const AppStack = createStackNavigator(); const AppStackNavigation = () => { const headerHeight = useHeaderHeight(); // <-- ERROR console.log(headerHeight); render ( //... ) }
The hook is defined here: https://github.com/react-navigation/react-navigation/blob/5.x/packages/stack/src/utils/useHeaderHeight.tsx
If you know it's a safe operation, you can define your own hook as
import { HeaderHeightContext } from '@react-navigation/stack';
const useHeaderHeight = () => {
const height = React.useContext(HeaderHeightContext);
if (height === undefined) {
return 0;
}
return height;
};
Then use it instead of the one provided by react-navigation
😉
Hey! This issue is closed and isn't watched by the core team. You are welcome to discuss the issue with others in this thread, but if you think this issue is still valid and needs to be tracked, please open a new issue with a repro.
How do i get the height of the StackNavigator header programmatically?
I need to detect if component A's position is within component B when pan gesture (drag) on A is released. However, the position from
onPanResponderRelease
'sgesture.moveY
is measured with respect to the entire screen, whereas the position returned from A'sonLayout
is measured with respect to the parent view. So i'd need to know the parent view's current height to reconcile the differences.