javascript - 添加带有 Stack Navigator 的 TabNavigator(版本 : 3. x)

标签 javascript react-native

我正在尝试在我的项目中添加选项卡导航器。这是一个使用 React Native 开发的天气应用程序。我尝试在屏幕中添加选项卡导航器,但它从未起作用。我尝试添加它与很多教程...

这是我的代码:

App.js

import SearchScreen from "./screens/search-screen";
import store from "./store";
import {Provider} from "react-redux"
import {createStackNavigator, createAppContainer} from "react-navigation";
import AdvancedDetailScreen from "./screens/advanced-detail-screen";

export default class App extends React.Component {

  render() {

  return (
      <Provider store={store}>
<Routes />
      </Provider>
  );
}
}

const StackNavigator = createStackNavigator({
    Search : SearchScreen,
    Detail: AdvancedDetailScreen
},
    {
        initialRouteName: "Search",
        headerMode: "none"
    }
);

const Routes = createAppContainer(StackNavigator);


高级细节屏幕.js:

import {connect} from "react-redux";
import {View, Text, Button} from "react-native";
import {withNavigation} from "react-navigation";
import {getForecastWeatherByCity} from "../actions";
import {LineChart} from "react-native-chart-kit";
import {
    widthPercentageToDP as wp,
    heightPercentageToDP as hp
} from "react-native-responsive-screen";
import {kelvinToCelcius} from "../services/temperature";

class AdvancedDetailScreen extends Component {
    componentDidMount() {
        const city = this.props.navigation.getParam("city");
        this.props.getForecastWeatherByCity(city);
    }
    getTemperatures(){
        return this.props.forecastWeather.list.map(weather => {
            return (kelvinToCelcius(weather.main.temp))
        })
    }
    getHumidity(){
        return this.props.forecastWeather.list.map(weather => {
            return (kelvinToCelcius(weather.main.humidity))
        })
    }
    getLabels(){
        return this.props.forecastWeather.list.map((_,index) => {
            let day = index / 8
            return index === 0 ?  "t" : index % 8 === 0 ? "t+" + day + "j" : ""
        })
    }
    renderChart(data){
        return(
            <LineChart
                data={{
                    labels: this.getLabels(),
                    datasets: [
                        {
                            data
                        }
                    ]
                }}
                width={wp("90%")} // from react-native
                height={hp("30%")}

                yAxisInterval={1} // optional, defaults to 1
                chartConfig={{
                    backgroundColor: "#e26a00",
                    backgroundGradientFrom: "#fb8c00",
                    backgroundGradientTo: "#ffa726",
                    decimalPlaces: 2, // optional, defaults to 2dp
                    color: (opacity = 1) => `rgba(255, 255, 255, ${opacity})`,
                    labelColor: (opacity = 1) => `rgba(255, 255, 255, ${opacity})`,
                    style: {
                        borderRadius: 16
                    },
                    propsForDots: {
                        r: "6",
                        strokeWidth: "2",
                        stroke: "#ffa726"
                    }
                }}
                bezier
                style={{
                    marginVertical: 8,
                    borderRadius: 16
                }}
            />
        )
    }
    goBack = () => {
        this.props.navigation.goBack();
};
    renderCharts(){
        return(
            <View style={{alignItems:"center", justifyContent: "center"}}>
                <Text style={{fontSize: 30, paddingTop: hp("1%")}}>
                    {this.props.forecastWeather.city.name} 5 days forecast
                </Text>
                <Text style={{marginBottom: hp("2%"), fontSize: 20}}>
                    Temperatures (C°)
                </Text>
                {this.renderChart(this.getTemperatures())}
                <Text style={{marginBottom: hp("2%"), fontSize: 20}}>
                    Humidity (%)
                </Text>
                {this.renderChart(this.getHumidity())}
                <Button onPress={this.goBack} title="Back" containerStyle={{marginTop: hp("1%"), width:wp("90%")}} />
            </View>
        )
    }
    render() {
        return (
            <View style={{justifyContent: "center", alignItems: "center", flex: 1}}>
                {this.props.forecastWeather ? this.renderCharts() : <Text>Loading...</Text>}
            </View>);
    }
}

const mapStateToProps = state => {
    return {
        forecastWeather: state.weather.forecastWeather
    };
};
const mapDispatchToProps = {
    getForecastWeatherByCity
};

export default withNavigation(connect(mapStateToProps, mapDispatchToProps)(AdvancedDetailScreen));

还有我的 search-screen.js :

import { StyleSheet, Text, View } from 'react-native';
import MapView from 'react-native-maps';
import {SearchBar} from "react-native-elements";
import {
    widthPercentageToDP as wp,
    heightPercentageToDP as hp
} from "react-native-responsive-screen";
import {connect} from "react-redux";
import {getCurrentWeatherByCity} from "../actions/index";
import WeatherCard from "../components/weather-card";

const DEFAULT_COORD = {
    lat: 48.859268,
    lng: 2.347060
};
class SearchScreen extends React.Component {
    state={search: ""};
    updateSearch = search => {
        this.setState({search})
    };
    submitSearch = () => {
        this.props.getCurrentWeatherByCity(this.state.search);
        console.log(this.state.search)
    };
    render() {
console.log(this.props.currentWeather);
        return (
            <View style={styles.container}>
                <MapView style={{flex : 1}}
                         region={{latitude : this.props.currentWeather ? this.props.currentWeather.coord.lat : DEFAULT_COORD.lat, longitude : this.props.currentWeather ? this.props.currentWeather.coord.lon : DEFAULT_COORD.lng, latitudeDelta: 0.2000, longitudeDelta: 0.1000}}
                         scrollEnabled={false}
                         liteMode={true} />
                {this.props.currentWeather &&
                <WeatherCard currentWeather={this.props.currentWeather}> </WeatherCard> }
                <SearchBar
                    lightTheme
                    onChangeText={this.updateSearch}
                    value={this.state.search}
                    onSubmitEditing={this.submitSearch}
                    containerStyle={{
                        position: "absolute",
                        bottom: hp("50%"),
                        left: wp("5%"),
                        width: wp("90%")

                    }}/>



            </View>
        );
    }
}

const styles = StyleSheet.create({
    container: {
        flex: 1

    },
});
const mapStateToProps = (store) => {
    return {
        currentWeather : store.weather.currentWeather
    }
};
const mapDispatchToProps = {
    getCurrentWeatherByCity
};
export default connect(mapStateToProps, mapDispatchToProps)(SearchScreen)

我真的不明白我做错了什么,所以如果我能得到帮助那就太棒了。 我是一个初学者,所以如果我做了一些废话,请不要责怪我,但欢迎任何建议!

最佳答案

既然你提到你当前的react-navigation的版本是^3.1.5,我会给你一个项目的例子。例如,如果您想更改主屏幕中的 stackNavigator (这意味着将通过选项卡访问搜索和详细信息屏幕),那么您要做的就是将其更改为 createBottomNavigator。那么,你的代码应该是这样的:

import SearchScreen from "./screens/search-screen";
import store from "./store";
import {Provider} from "react-redux"
import { createBottomTabNavigator, createAppContainer } from 'react-navigation'; //change this line
import AdvancedDetailScreen from "./screens/advanced-detail-screen";

export default class App extends React.Component {

  render() {

  return (
      <Provider store={store}>
<Routes />
      </Provider>
  );
}
}

//change this to become tabnavigation
const TabNavigator = createBottomTabNavigator({ 
  Search : SearchScreen,
Detail: AdvancedDetailScreen
}); //Search will be default primary screen which is first to shown

const Routes = createAppContainer(StackNavigator);

更新

抱歉,因为在react-navigation v.3中createAppContainer的配置是这样的。是的,您可以将它们保存在同一个文件中。

import SearchScreen from "./screens/search-screen";
import store from "./store";
import {Provider} from "react-redux"
import {createStackNavigator, createBottomTabNavigator, createAppContainer} from "react-navigation";
import AdvancedDetailScreen from "./screens/advanced-detail-screen";

export default class App extends React.Component {

  render() {

  return (
      <Provider store={store}>
<Routes />
      </Provider>
  );
}
}

const StackNavigator = createStackNavigator({
    Search : SearchScreen,
    Detail: AdvancedDetailScreen
},
    {
        initialRouteName: "Search",
        headerMode: "none"
    }
);

const TabNavigator = createBottomTabNavigator({ 
  Search : SearchScreen,
  Detail: AdvancedDetailScreen
}); //Put it together not working like this


const Routes = createAppContainer(TabNavigator, StackNavigator); //This line has been edited

它有效,但这意味着您正在尝试为应用程序中的每个屏幕放置选项卡。因为你把它和路线放在一起了。另一个例子:https://snack.expo.io/xu1Tiudf !

文档:https://reactnavigation.org/docs/3.x/navigating https://reactnavigation.org/docs/3.x/tab-based-navigation

关于javascript - 添加带有 Stack Navigator 的 TabNavigator(版本 : 3. x),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61426773/

相关文章:

javascript - 如何在 React Native 中截图测试?

animation - react native : Continue animation with last velocity of touch gesture

android - React Native + Android:transformClassesWithDexForDebug失败

javascript - React Native 模态不关闭

javascript - 如何根据 .csv 报告中的数值以及动态创建表格时更改表格单元格颜色?

javascript - 使用特定语法对 Controller 进行单元测试

flexbox - 文本组件的样式部分

javascript - 如何只让那些 props 传递给组件,组件是根据 switch 决定的

php - 在 jquery 中返回被点击的 li 的值

javascript - 如何在 native react 中获取数字的整数和小数部分