June January
June January

Reputation: 123

how get parent size in child view in react-native?

I cannot understand how can I send parent view's sizes to child component of this. In renderPager() I want calculate some parameters that depend on parent view size. I know that we can do it through onLayout(). problem is that onLayout will be called only after building all of childs (I see it by the console log). how can I do it?

     onPageLayout = (event) => {
        const { width, height } = event.nativeEvent.layout;
        console.log("ON LAYOUT");
      }; 

    render() {
        return (
          <View
            style={styles.root}
            onLayout={this.onPageLayout}
          >
            {this.renderPager()}
          </View>
        );
      }
    
    renderPager = () => {
       // how can get root view's size here
        return (
          <IndicatorViewPager
            ref={(ref) => (this.viewPager = ref)}
            scrollEnabled={!this.state.isDragging}
            onPageScroll={this.onPageScroll}
            style={styles.pageRoot}
          >
            {this.renderPages()}
          </IndicatorViewPager>
        );
      };

thank you

Upvotes: 11

Views: 29011

Answers (2)

Nicolas Sturm
Nicolas Sturm

Reputation: 691

https://gist.github.com/sturmenta/2bf6fa1e58d30c5977810b737c6173c0

import React, {useState} from 'react';
import {View, ViewProps} from 'react-native';

interface ContainerWithDimensionsProps extends ViewProps {
  children: ({
    width,
    height,
  }: {
    width: number;
    height: number;
  }) => React.ReactNode;
}

export const ContainerWithDimensions: React.FC<
  ContainerWithDimensionsProps
> = ({children, ...props}: ContainerWithDimensionsProps) => {
  const [dimensions, setDimensions] = useState({width: 0, height: 0});

  return (
    <View
      onLayout={event =>
        setDimensions({
          width: event.nativeEvent.layout.width,
          height: event.nativeEvent.layout.height,
        })
      }
      {...props}>
      {children(dimensions)}
    </View>
  );
};

// ────────────────────────────────────────────────────────────────────────────────
// usage

// <ContainerWithDimensions>
//   {({width, height}) => {
//     console.log('width', width);
//     console.log('height', height);
//     return <View />;
//   }}
// </ContainerWithDimensions>;

Upvotes: 2

martinarroyo
martinarroyo

Reputation: 9701

You can maybe pass the data as props, and take the prop data from the store. You are right in that onLayout will only be triggered after everything is rendered, but that simply means that you have to pass the props with a null value on the first render. For instance:

    onPageLayout = (event) => {
        const { width, height } = event.nativeEvent.layout;
        console.log("ON LAYOUT");
        this.setState({width, height})
      }; 
    
    render() {
        return (
          <View
            style={styles.root}
            onLayout={this.onPageLayout}
          >
            {this.renderPager(this.state.width, this.state.height)}
          </View>
        );
      }
    
    renderPager = (width, height) => {
       // Do something if width or height are null
       // how can get root view's size here
        return (
          <IndicatorViewPager
            ref={(ref) => (this.viewPager = ref)}
            scrollEnabled={!this.state.isDragging}
            onPageScroll={this.onPageScroll}
            style={styles.pageRoot}
          >
            {this.renderPages()}
          </IndicatorViewPager>
        );
      };

Also you could use the measure function of the parent, but I think that might be a bit cumbersome.

Upvotes: 8

Related Questions