不断获取“未定义不是对象(评估'this.props.navigation.navigate')”

时间:2019-04-29 11:59:40

标签: react-native react-navigation

我是本机反应的新手,而且我能够参加一个新项目。但是,我似乎无法从入职屏幕导航,因为我不断得到未定义的错误不是对象。

  

评估“ this.props.navigation.navigate”

我已经处理了大约一个星期,但一直无法找到解决方案。下面是我的源代码。

Index.js

import { AppRegistry } from 'react-native';
import App from './App';

AppRegistry.registerComponent('AppName', () => App);

App.js

import React, { Component } from 'react';
import {
    Text,
    View,
    AppRegistry
} from 'react-native';
import SplashScreen from 'react-native-splash-screen';
import { StackNavigator } from 'react-navigation';
import OnBoardingScreen from './src/components/onboarding/OnBoardingScreen';
import Home from './src/components/Home';

const OnBoardingRoutes = StackNavigator({
    OnBoardingScreen:
    {
        screen: OnBoardingScreen,
        navigationOptions: {
            header: null
        },
    },
    Home:
    {
        screen: Home,
        navigationOptions: {
            header: null
        },
    },
},
    {
        initialRouteName: 'OnBoardingScreen'
    }
);

const LoginStack = StackNavigator({
    OnBoardingScreen:
    {
        screen: OnBoardingScreen,
        navigationOptions: {
            header: null
        },
    },
    Home:
    {
        screen: Home,
        navigationOptions: {
            header: null
        },
    },
},
    {
        initialRouteName: 'Home'
    }
);

type Props = {};
class App extends Component<Props> {

    constructor(props) {
        super(props);
    }

    componentDidMount() {
        SplashScreen.hide();
    }

    render() {
        return (
            <OnBoardingRoutes />
        );
    }
}

export default App;

swiper.js(入职)

/**
 * Swiper
 * Renders a swipable set of screens passed as children,
 * pagination indicators and a OnBoardingButton to swipe through screens
 * or to get out of the flow when the last screen is reached
 */

import React, { Component } from 'react';
import {
    Dimensions,       // Detects screen dimensions
    Platform,         // Detects platform running the app
    ScrollView,       // Handles navigation between screens
    StyleSheet,       // CSS-like styles
    View,             // Container component
} from 'react-native';
import OnBoardingButton from '../buttons/OnBoardingButton';
import Home from '../Home';

// Detect screen width and height
const { width, height } = Dimensions.get('window');

export default class Swiper extends Component {

    static navigationOptions = {
        header: null,
    }

    // Props for ScrollView component
    static defaultProps = {
        // Arrange screens horizontally
        horizontal: true,
        // Scroll exactly to the next screen, instead of continous scrolling
        pagingEnabled: true,
        // Hide all scroll indicators
        showsHorizontalScrollIndicator: false,
        showsVerticalScrollIndicator: false,
        // Do not bounce when the end is reached
        bounces: false,
        // Do not scroll to top when the status bar is tapped
        scrollsToTop: false,
        // Remove offscreen child views
        removeClippedSubviews: true,
        // Do not adjust content behind nav-, tab- or toolbars automatically
        automaticallyAdjustContentInsets: false,
        // Fisrt is screen is active
        index: 0
    };

    constructor(props) {
        super(props);
        this.home = this.home.bind(this);
    }

    home() {
        this.props.navigation.navigate('Home');
    }

    /**
     * Render Continue or Done OnBoardingButton
     */

    renderOnBoardingButton = () => {
        const lastScreen = this.state.index === this.state.total - 1;
        return (
            <View pointerEvents="box-none" style={[styles.OnBoardingButtonWrapper, styles.fullScreen]}>
                {lastScreen
                    // Show this OnBoardingButton on the last screen
                    // TODO: Add a handler that would send a user to your app after onboarding is complete
                    ? <OnBoardingButton text="Start Now" onPress={() => this.home()} />
                    // Or this one otherwise
                    : <OnBoardingButton text="Continue" onPress={() => this.swipe()} />
                }
            </View>
        );
    }

    state = this.initState(this.props);

    /**
     * Initialize the state
     */
    initState(props) {
        // Get the total number of slides passed as children
        const total = props.children ? props.children.length || 1 : 0,
            // Current index
            index = total > 1 ? Math.min(props.index, total - 1) : 0,
            // Current offset
            offset = width * index;

        const state = {
            total,
            index,
            offset,
            width,
            height,
        };

        // Component internals as a class property,
        // and not state to avoid component re-renders when updated
        this.internals = {
            isScrolling: false,
            offset
        };

        return state;
    }

    /**
     * Scroll begin handler
     * @param {object} e native event
     */
    onScrollBegin = e => {
        // Update internal isScrolling state
        this.internals.isScrolling = true;
    }

    /**
     * Scroll end handler
     * @param {object} e native event
     */
    onScrollEnd = e => {
        // Update internal isScrolling state
        this.internals.isScrolling = false;

        // Update index
        this.updateIndex(e.nativeEvent.contentOffset
            ? e.nativeEvent.contentOffset.x
            // When scrolled with .scrollTo() on Android there is no contentOffset
            : e.nativeEvent.position * this.state.width
        );
    }

    /*
     * Drag end handler
     * @param {object} e native event
     */
    onScrollEndDrag = e => {
        const { contentOffset: { x: newOffset } } = e.nativeEvent,
            { children } = this.props,
            { index } = this.state,
            { offset } = this.internals;

        // Update internal isScrolling state
        // if swiped right on the last slide
        // or left on the first one
        if (offset === newOffset &&
            (index === 0 || index === children.length - 1)) {
            this.internals.isScrolling = false;
        }
    }

    /**
     * Update index after scroll
     * @param {object} offset content offset
     */
    updateIndex = (offset) => {
        const state = this.state,
            diff = offset - this.internals.offset,
            step = state.width;
        let index = state.index;

        // Do nothing if offset didn't change
        if (!diff) {
            return;
        }

        // Make sure index is always an integer
        index = parseInt(index + Math.round(diff / step), 10);

        // Update internal offset
        this.internals.offset = offset;
        // Update index in the state
        this.setState({
            index
        });
    }

    /**
     * Swipe one slide forward
     */
    swipe = () => {
        // Ignore if already scrolling or if there is less than 2 slides
        if (this.internals.isScrolling || this.state.total < 2) {
            return;
        }

        const state = this.state,
            diff = this.state.index + 1,
            x = diff * state.width,
            y = 0;

        // Call scrollTo on scrollView component to perform the swipe
        this.scrollView && this.scrollView.scrollTo({ x, y, animated: true });

        // Update internal scroll state
        this.internals.isScrolling = true;

        // Trigger onScrollEnd manually on android
        if (Platform.OS === 'android') {
            setImmediate(() => {
                this.onScrollEnd({
                    nativeEvent: {
                        position: diff
                    }
                });
            });
        }
    }

    /**
     * Render ScrollView component
     * @param {array} slides to swipe through
     */
    renderScrollView = pages => {
        return (
            <ScrollView ref={component => { this.scrollView = component; }}
                {...this.props}
                contentContainerStyle={[styles.wrapper, this.props.style]}
                onScrollBeginDrag={this.onScrollBegin}
                onMomentumScrollEnd={this.onScrollEnd}
                onScrollEndDrag={this.onScrollEndDrag}
            >
                {pages.map((page, i) =>
                    // Render each slide inside a View
                    <View style={[styles.fullScreen, styles.slide]} key={i}>
                        {page}
                    </View>
                )}
            </ScrollView>
        );
    }

    /**
     * Render pagination indicators
     */
    renderPagination = () => {
        if (this.state.total <= 1) {
            return null;
        }

        const ActiveDot = <View style={[styles.dot, styles.activeDot]} />,
            Dot = <View style={styles.dot} />;

        let dots = [];

        for (let key = 0; key < this.state.total; key++) {
            dots.push(key === this.state.index
                // Active dot
                ? React.cloneElement(ActiveDot, { key })
                // Other dots
                : React.cloneElement(Dot, { key })
            );
        }

        return (
            <View
                pointerEvents="none"
                style={[styles.pagination, styles.fullScreen]}
            >
                {dots}
            </View>
        );
    }

    /**
     * Render the component
     */
    render = ({ children } = this.props) => {
        return (
            <View style={[styles.container, styles.fullScreen]}>
                {/* Render screens */}
                {this.renderScrollView(children)}
                {/* Render pagination */}
                {this.renderPagination()}
                {/* Render Continue or Done OnBoardingButton */}
                {this.renderOnBoardingButton()}
            </View>
        );
    }
}

const styles = StyleSheet.create({
    // Set width and height to the screen size
    fullScreen: {
        width: width,
        height: height
    },
    // Main container
    container: {
        backgroundColor: 'transparent',
        position: 'relative'
    },
    // Slide
    slide: {
        backgroundColor: 'transparent'
    },
    // Pagination indicators
    pagination: {
        position: 'absolute',
        bottom: 110,
        left: 0,
        right: 0,
        flex: 1,
        flexDirection: 'row',
        justifyContent: 'center',
        alignItems: 'flex-end',
        backgroundColor: 'transparent'
    },
    // Pagination dot
    dot: {
        backgroundColor: 'rgba(0,0,0,.25)',
        width: 8,
        height: 8,
        borderRadius: 4,
        marginLeft: 3,
        marginRight: 3,
        marginTop: 3,
        marginBottom: 3
    },
    // Active dot
    activeDot: {
        backgroundColor: '#FFFFFF',
    },
    // Button wrapper
    OnBoardingButtonWrapper: {
        backgroundColor: 'transparent',
        flexDirection: 'column',
        position: 'absolute',
        bottom: 0,
        left: 0,
        flex: 1,
        paddingHorizontal: 10,
        paddingVertical: 40,
        justifyContent: 'flex-end',
        alignItems: 'center'
    },
});

2 个答案:

答案 0 :(得分:0)

您正在使用哪个版本的React Navigation? 您确定设置正确吗,因为他们已经更改了设置方式 从版本3开始对导航做出反应?

尝试一下...

import { createAppContainer } from 'react-navigation';

//assuming you have OnBoardingRoutes as entry screen in App
const AppContainer = createAppContainer(OnBoardingRoutes);

然后在App.js的呈现方法中返回AppContainer

return (
   <AppContainer />
) 

答案 1 :(得分:0)

我已经能够使用withNavigation对其进行修复