You need to enable JavaScript to run this app. 如何将类组件改写为函数组件且可在Stack Navigation中作为屏幕使用
优惠活动
大模型
产品
解决方案
定价
更多

如何将类组件改写为函数组件且可在Stack Navigation中作为屏幕使用

解决方案

核心问题说明

  • 错误1:React.useState 是Hook,仅允许在函数组件顶层作用域调用,你在TermsAndCondition.js的组件外部直接声明导出isAccepted,必然触发Hook调用报错,且这个全局状态无法触发App组件重渲染。
  • 错误2:无法直接从子组件导出内部state供父组件使用,你导入的isAccepted没有实际响应式效果。
  • 错误3:判断逻辑写反:用户未同意时应该显示条款页,同意后显示主页,你当前的三元判断逻辑完全相反。

修改步骤

1. 调整App.js代码

把同意状态存在App组件内部,给条款页传递同意回调,修改后代码如下:

import { NavigationContainer } from "@react-navigation/native";
import "react-native-gesture-handler";
import { createStackNavigator } from "@react-navigation/stack";
import React from "react";

import mapScreen1 from "./src/screens/mapScreen1";
import mapListScreen from "./src/screens/mapListScreen";
import Home from "./src/screens/Home";
import TermsAndConditions from "./src/screens/termscond";

const Stack = createStackNavigator();

export default class App extends React.Component {
  // 存储条款同意状态
  state = {
    isTermsAccepted: false
  }
  // 同意条款的回调方法
  handleAcceptTerms = () => {
    this.setState({ isTermsAccepted: true })
    // 如需持久化存储(下次打开无需再同意),可在这里调用AsyncStorage写入状态,启动时读取即可
  }

  render() {
    return (
      <NavigationContainer>
        {!this.state.isTermsAccepted ? (
          <Stack.Navigator screenOptions={{headerShown: false}}>
            <Stack.Screen
              name="Terms and Conditions"
              // 给条款页传递回调方法
              component={() => <TermsAndConditions onAccept={this.handleAcceptTerms} />}
            />
          </Stack.Navigator>
        ) : (
          <Stack.Navigator>
            <Stack.Screen name="Home" component={Home} />
            <Stack.Screen name="mapListScreen" component={mapListScreen} />
            <Stack.Screen name="mapScreen1" component={mapScreen1} />
          </Stack.Navigator>
        )}
      </NavigationContainer>
    );
  }
}

2. 调整TermsAndCondition.js代码

删掉外部错误的useState声明,接收父组件传递的onAccept回调,修改后代码如下:

import React, { Component } from "react";
import {
  View,
  Text,
  ScrollView,
  TouchableOpacity,
  StyleSheet
} from "react-native";

const isCloseToBottom = ({ layoutMeasurement, contentOffset, contentSize }) => {
  const paddingToBottom = 20;
  return (
    layoutMeasurement.height + contentOffset.y >=
    contentSize.height - paddingToBottom
  );
};

export default class TermsAndConditions extends Component {
  state = {
    accepted: false,
  };

  render() {
    return (
      <View style={styles.container}>
        <Text style={styles.title}>Terms and conditions</Text>
        <ScrollView
          style={styles.tcContainer}
          onScroll={({ nativeEvent }) => {
            if (isCloseToBottom(nativeEvent)) {
              this.setState({
                accepted: true,
              });
            }
          }}
        >
          <Text style={styles.tcP}>
            Welcome to our website. Terms And Condition.
          </Text>
        </ScrollView>

        <TouchableOpacity
          disabled={!this.state.accepted}
          // 点击时调用父组件传递的同意回调
          onPress={this.props.onAccept}
          style={this.state.accepted ? styles.button : styles.buttonDisabled}
        >
          <Text style={styles.buttonLabel}>Accept</Text>
        </TouchableOpacity>
      </View>
    );
  }
}

// 补充基础样式,可根据需求自行修改
const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 20,
    backgroundColor: '#fff'
  },
  title: {
    fontSize: 24,
    fontWeight: 'bold',
    marginBottom: 20
  },
  tcContainer: {
    flex: 1,
    marginBottom: 20
  },
  tcP: {
    fontSize: 16,
    lineHeight: 24
  },
  button: {
    backgroundColor: '#2196F3',
    padding: 15,
    borderRadius: 5,
    alignItems: 'center'
  },
  buttonDisabled: {
    backgroundColor: '#ccc',
    padding: 15,
    borderRadius: 5,
    alignItems: 'center'
  },
  buttonLabel: {
    color: '#fff',
    fontSize: 16,
    fontWeight: 'bold'
  }
})

内容的提问来源于stack exchange,提问作者Kmaza04

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.20 05:45:05