使用从API调用获取的数据更新TabNavigator标签

时间:2019-08-16 10:34:46

标签: javascript reactjs react-native react-navigation

我有一个具有多个堆栈导航器的应用程序,其中一个具有内部的createMaterialTopTabNavigator,可向我显示一个列表。现在,对于每个选项卡,我都获得了其中的项目计数,我通过单独的API调用获取了这些计数(所有选项卡的计数均通过单个API提取)。默认情况下,我能够显示一个静态的tabLabel。 我需要做的是在其标签(标签标题)中显示每个标签的数量。

导航器代码:

import React from "react";
import { View } from "react-native";
import { createMaterialTopTabNavigator } from "react-navigation";
import SellerListingScreen from "screens/App/SellerListingScreen/SellerListingScreen";

const SellerListingNavigator = createMaterialTopTabNavigator(
  {
    PendingSellers: {
      screen: () => <SellerListingScreen type={0} />,
      navigationOptions: {
        title: "Pending(<show count here>)"
      }
    },
    CompletedSellers: {
      screen: () => <SellerListingScreen type={1} />,
      navigationOptions: {
        title: "Completed(<show count here>)"
      }
    }
  },
  {
    tabBarOptions: {
      style: {
        backgroundColor: "#00cc99"
      }
    },
    lazy: true
  }
);

export default SellerListingNavigator;

2 个答案:

答案 0 :(得分:1)

使用react-navigation时,navigationOptions可以是静态对象(如您当前示例中的对象),也可以是采用包含navigation对象的对象的函数。就您而言,您可以像这样轻松地重写您的navigationOptions:

({navigation}) => {
  const fetchDone = navigation.getParam('countFetchDone');
  const currentCount = navigation.getParam('count');
  if (!fetchDone) {
    navigation.setParam('countFetchDone', true);
    fetch(YOUR_FETCH_OPTIONS_HERE)
      .then((r) => r.json())
      .then((data) => {
        navigation.setParam('count', data.count);
      });
  }
  if (currentCount !== undefined) {
    return {
      title: 'My list (' + currentCount + ')'
    };
  } else {
    return {
      title 'My list (...)'
    };
  }
}

您需要将查询状态另存为参数,以使标头正确更新(因为仅在参数更改时才更新)。 fetchDone用于确保查询完成一次。

答案 1 :(得分:1)

好吧,我设法通过创建一个自定义的导航器白色解决了这个问题,该导航器扩展了我现有的tabNavigator并将必需的参数传递给screenProps

import React from "react";
import { createMaterialTopTabNavigator } from "react-navigation";
// @ts-ignore
import SellerListingScreen from "screens/App/SellerListingScreen/SellerListingScreen";
// @ts-ignore
import { getItem } from "utils/interactAsyncStorage";

const SellerListingNavigator = createMaterialTopTabNavigator(
  {
    PendingSellers: {
      screen: () => <SellerListingScreen type={0} />,
      navigationOptions: ({ screenProps }) => ({
        title: `Pending (${screenProps.pending})`
      })
    },
    CompletedSellers: {
      screen: () => <SellerListingScreen type={1} />,
      navigationOptions: ({ screenProps }) => ({
        title: `Completed (${screenProps.completed})`
      })
    }
  },
  {
    tabBarOptions: {
      style: {
        backgroundColor: "#00cc99"
      }
    },
    lazy: true
  }
);

class customSellerListingNavigator extends React.Component {
  constructor(props) {
    super(props);
    this.state = { pending: 0, completed: 0 };
  }
  static router = SellerListingNavigator.router;
  _fetchPickupCounts = async () => {
    const userData = await getItem("UserData");
    const headers = {
      "Content-Type": "application/json",
      "Session-Token": userData.sessionToken,
    };
    const baseUrl = "baseurl here";
    const url = `${baseUrl}/pickupCount/`;

    return await fetch(url, {
      method: "post",
      headers: headers
    })
      .then(response => response.json())
      .then(responseJson => {
        this.setState({
          pending: responseJson.pending,
          completed: responseJson.completed
        });
      })
      .catch(error => {
        console.error(error);
      });
  };

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

    return (
      <SellerListingNavigator
        navigation={navigation}
        screenProps={{
          pending: this.state.pending,
          completed: this.state.completed
        }}
      />
    );
  }
}

export default customSellerListingNavigator;