Search code examples
react-nativelaravel-api

Unable to render View inside ScrollableTabView


I'm new to React Native, and i'm trying to use Tabs using this package https://github.com/LiuC520/react-native-scrollable-tab-view-forked, this is how the tabs created

<ScrollableTabView

   renderTabBar={() => (
       <ScrollableTabBar
       style={styles.scrollStyle}
            tabStyle={styles.tabStyle}
          />
        )}
        tabBarTextStyle={styles.tabBarTextStyle}
        tabBarInactiveTextColor={'black'}
        tabBarActiveTextColor={'red'}
        tabBarUnderlineStyle={styles.underlineStyle}
        initialPage={2}
      >

        <View key={'1'} tabLabel={'firt tab '} style={{flex:1,backgroundColor:'red'}}/>
        <View key={'2'} tabLabel={'second tab'} style={{flex:1,backgroundColor:'blue'}}/>
        <View key={'3'} tabLabel={'third tab'} style={{flex:1,backgroundColor:'yellow'}}/>
</ScrollableTabView>

And it's working fine

but when i'm trying to render view to display it inside every tab i failed, i've tried this way

<View key={'1'} tabLabel={'firt tab '} style={{flex:1,backgroundColor:'red',height:100}}>
    <View><Text>first</Text></View>
</View>

but it gives error "TypeError: JSON.stringify cannot serialize cyclic structure", i don't what that mean, if any one have already worked with this package or know what's the solution please help.

this is my whole code

import React from 'react';
import { ScrollView, ImageBackground, Image, View, StyleSheet, 
StatusBar, Dimensions, Platform } from 'react-native';
import { Block, Button, Text, theme } from 'galio-framework';
import ScrollableTabView, { DefaultTabBar, ScrollableTabBar } from 'react-native-scrollable-tab-view-forked';

const { height, width } = Dimensions.get('screen');
import { Images, argonTheme } from '../constants/';
import { HeaderHeight } from "../constants/utils";
import ajax from '../services/FetchSubjects';
import Loader from '../components/Loader';

const URI = 'http://localhost:8000';

export default class SubjectDetails extends React.Component {

  constructor(props) {
    super(props);
    this.state = {
     loading: true,
     data: {
      subject: {},
      meals: []
    }
  }
 }  
 async componentDidMount() {
  const data = await ajax.fetchSubjectDetails(this.props.navigation.state.params.subjectId);
this.setState({
  data: {
    subject: data.subject,
    meals: data.meals
  },
  loading: false
 });
}

render() {
  const { navigation } = this.props;

  return (
   <Block safe style={styles.container}>
    <Block>
      <StatusBar barStyle="light-content" />
      <Loader loading={this.state.loading} />
      <Block flex style={styles.category}>
        <ImageBackground
          source={this.state.loading ? Images.Pro : { uri: URI + this.state.data.subject.cover.url }}
          style={{ flex: 1, height: 160, width, zIndex: 1 }}
        >
        <Block style={styles.categoryBg}>
          <Block style={styles.categoryTitle}>
            <Text size={18} bold color={theme.COLORS.WHITE}>
              {this.state.data.subject.name}
            </Text>
          </Block>
        </Block>
        </ImageBackground>
      </Block>
    </Block>
    <Block style={{marginTop:160,height:"100%"}}>
      <ScrollView>
        <ScrollableTabView

            renderTabBar={() => (
              <ScrollableTabBar
                style={styles.scrollStyle}
                tabStyle={styles.tabStyle}
              />
            )}
            tabBarTextStyle={styles.tabBarTextStyle}
            tabBarInactiveTextColor={'black'}
            tabBarActiveTextColor={'#2B4D8E'}
            tabBarUnderlineStyle={styles.underlineStyle}
            initialPage={2}
          >

          <View key={'1'} tabLabel={'firt tab '} style={{flex:1,backgroundColor:'red',height:100}}><Text>Lorem ipsum</Text></View>
          <View key={'2'} tabLabel={'second tab'} style={{flex:1,backgroundColor:'blue',height:100}}/>
          <View key={'3'} tabLabel={'third tab'} style={{flex:1,backgroundColor:'yellow',height:100}}/>
          <View key={'4'} tabLabel={'Fourth tab'} style={{flex:1,backgroundColor:'yellow',height:100}}/>
        </ScrollableTabView>
      </ScrollView>
    </Block>
  </Block>
  );
 }
}

Solution

  • ok, I read the react-native-scroll-tab-view and react-native-scroll-tab-view-forked source code, and find some code are different, which cause your problems. you should use react-native-scroll-tab-view.
    the reason is: firstly, we look at the source code, the ScrollTabview which located in the index.js, I only show the core code.

    // this is react-native-scroll-tab-view code
    let tabBarProps = {
          goToPage: this.goToPage,
          tabs: this._children().map((child) => child.props.tabLabel), //this is the diffent
          activeTab: this.state.currentPage,
          scrollValue: this.state.scrollValue,
          containerWidth: this.state.containerWidth,
        };
    // this is the fork project
    const tabBarProps = {
          goToPage: this.goToPage,
          tabs: this._children().map(child => child.props), //this is the diffent
          activeTab: this.state.currentPage,
          scrollValue: this.state.scrollValue,
          // containerWidth: this.props.containerWidth,
          containerWidth: this.props.tabsWidth || this.props.containerWidth,
          initialPage:this.props.initialPage,
        }
    // the tabs in the fored is not according by tablabel.
    
    // then it will call the this.renderTabBar method
    return <View style={[styles.container, this.props.style, ]} onLayout={this._handleLayout}>
          {this.props.tabBarPosition === 'top' && this.renderTabBar(tabBarProps)}
          {this.renderScrollableContent()}
          {(this.props.tabBarPosition === 'bottom' || overlayTabs) && this.renderTabBar(tabBarProps)}
        </View>;
    
    //in this.renderTabBar, you define the method, so it will call this.props.renderTabBar
    renderTabBar(props) {
        if (this.props.renderTabBar === false) {
          return null;
        } else if (this.props.renderTabBar) {
          return React.cloneElement(this.props.renderTabBar(props), props);
        } else {
          return <DefaultTabBar {...props} />;
        }
      },
    
     // then, we look at the ScrollTabBar soruce code, which will render tabs
     //here it call the JSON.stringfy, so here it is your errors occur
    componentDidUpdate(prevProps) {
        // If the tabs change, force the width of the tabs container to be recalculated
        if (JSON.stringify(prevProps.tabs) !== JSON.stringify(this.props.tabs) && this.state._containerWidth) {
          this.setState({ _containerWidth: null, });
        }
      },
    

    I hope it call help you!