Добавить TabNavigator с помощью стекового навигатора (версия: 3.x) - PullRequest
2 голосов
/ 25 апреля 2020

Я пытаюсь добавить вкладку Навигатор в свой проект. Это приложение Погода, разработанное с React native. Я пытался добавить вкладку навигатор на экране, но он никогда не работает. Я пытался добавить его с помощью множества учебных пособий ...

Вот мой код:

Приложение. 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);


advanced-detail-screen. 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));

И мой экран поиска. 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)

Я действительно не понимаю, что я делаю неправильно, поэтому, если я могу получить помощь, это будет будь офигенным. Я новичок, так что не сердитесь на меня, если я делаю какую-то чушь, но любые советы приветствуются!

1 Ответ

2 голосов
/ 25 апреля 2020

Поскольку вы упомянули версию вашей текущей реакции-навигации ^ 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);

ОБНОВЛЕНИЕ

Извините, поскольку конфигурация createAppContainer в response-navigation v.3 работает следующим образом. Да, вы можете хранить оба файла в одном файле.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...