3

I'm using react-native-tab-view and rendering two tabs.

I'm calling an api in the parent component, saving it to the parent state and then passing the state saved as prop to the child tabs.

But, I'm only receiving the initial state in the componentDidMount of the child tabs. However, in the render i'm able to receive the updated state from the api.

How can I get the final data in the componentDidMount of the child?

Here is how my parent component:

class Parent extends Component {
  state = {
    index: 0,
    data: [],
    routes: [{ key: 'tab1', title: 'Tab 1' }, { key: 'tab2', title: 'Tab 2' }],
  };

  componentDidMount() {
    this.getData();
  }

  getStudentList = async () => {
    axios
      .get('/api-url')
      .then(function(response) {
        // saving data to state
        this.setState({ data: response.data });
      })
      .catch(function(error) {
        // handle error
        console.log(error);
      });
  };

  renderScene = ({ route }) => {
    switch (route.key) {
      case 'tab1':
        return <Tab1 data={this.state.data} />; // passing data as data prop
      case 'tab2':
        return <Tab1 data={this.state.data} />;
      default:
        return null;
    }
  };

  handleIndexChange = index => {
    this.setState({ index });
  };

  render() {
    return (
      <TabView
        navigationState={this.state}
        renderScene={this.renderScene}
        renderTabBar={props => <TabBar {...props} />}
        onIndexChange={this.handleIndexChange}
      />
    );
  }
}

In my child tab component i'm not receiving the data from the api but the initial empty array.

Child component:

class Tab1 extends React.Component {
  componentDidMount() {
    console.log(this.props.data); // Logs out []
  }

  render() {
    console.log(this.props.data); // gives the api data
    return (
      <SafeAreaView style={styles.container}>
        <Text>Child</Text>
      </SafeAreaView>
    );
  }
}
vikrantnegi
  • 2,252
  • 5
  • 24
  • 35

2 Answers2

1

I don't know this.getData() did what, but I think componentDidMount get initial data, because you used setState. setState is Asynchronous method, so states change after componentDidMount get states.

How about using componentDidUpdate? I think it will work because it start after rendering and updating.

I hope it helps.

hughugh
  • 217
  • 3
  • 10
  • this.getData is just an api call. There should be some way to re-render the tabs when the setSate occurs, so that after re-render the component can get the new state. Although, the CDU works. – vikrantnegi Jan 31 '20 at 07:56
  • @vikrantnegi007 as I know, re-render doesn't matter with componentDidmount. `componentDidmount` just call once when the page render at the first time. re-render doesn't call componentDidmount – hughugh Jan 31 '20 at 08:45
  • I think you are correct. Anyways, I think componentDidUpdate will work. I'll try to get it working with CDU and mark this answer once i'm done. Thanks guys. – vikrantnegi Jan 31 '20 at 09:15
0

May be because setstate is asynchronous, and in the very next event of parent render or child component did mount it is not showing the data, but after that in child render it shows. Try callback after setstate in parent with just a console.log() and check.

Ranu Vijay
  • 1,137
  • 9
  • 18
  • I'm able to access the new data in the renderScene but I think the tabs are not re-rendering after setState. – vikrantnegi Jan 31 '20 at 07:57
  • if what you are thinking is correct then by default react renders every time when there is a state change. "render should be a pure state and props function". the problem then is in the way of writing code. Let me check again – Ranu Vijay Jan 31 '20 at 08:03