错误:元素类型无效:预期为字符串或类/函数,但得到:升级React Native后未定义

时间:2020-08-23 21:27:05

标签: react-native react-native-android

我有以下js:

import React, { useState, useEffect, useRef } from 'react';
import {
  Text,
  View,
  TextInput,
  Alert,
  Image,
  TouchableOpacity,
} from 'react-native';
import 'react-native-get-random-values';
import Button from 'react-native-button';
import PhoneInput from 'react-native-phone-input';
import { FirebaseRecaptchaVerifierModal } from 'expo-firebase-recaptcha';
import CodeField from 'react-native-confirmation-code-field';
import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view';
import { useColorScheme } from 'react-native-appearance';
import TNActivityIndicator from '../../truly-native/TNActivityIndicator';
import TNProfilePictureSelector from '../../truly-native/TNProfilePictureSelector/TNProfilePictureSelector';
import CountriesModalPicker from '../../truly-native/CountriesModalPicker/CountriesModalPicker';
import { IMLocalized } from '../../localization/IMLocalization';
import { setUserData } from '../redux/auth';
import { connect } from 'react-redux';
import authManager from '../utils/authManager';
import { localizedErrorMessage } from '../utils/ErrorCode';
import TermsOfUseView from '../components/TermsOfUseView';
import { firebase } from '../../firebase/config';
import dynamicStyles from './styles';

const SmsAuthenticationScreen = (props) => {
  const appConfig =
    props.navigation.state.params.appConfig ||
    props.navigation.getParam('appConfig');
  const appStyles =
    props.navigation.state.params.appStyles ||
    props.navigation.getParam('appStyles');

  const colorScheme = useColorScheme();
  const styles = dynamicStyles(appStyles, colorScheme);

  const [firstName, setFirstName] = useState('');
  const [lastName, setLastName] = useState('');
  const [loading, setLoading] = useState(false);
  const [isPhoneVisible, setIsPhoneVisible] = useState(true);
  const [phoneNumber, setPhoneNumber] = useState(false);
  const [countriesPickerData, setCountriesPickerData] = useState(null);
  const [verificationId, setVerificationId] = useState(null);
  const [profilePictureURL, setProfilePictureURL] = useState(null);
  const [countryModalVisible, setCountryModalVisible] = useState(false);
  const myCodeInput = useRef(null);
  const phoneRef = useRef(null);
  const recaptchaVerifier = React.useRef(null);
  const firebaseConfig = firebase.app().options;

  const { isSigningUp } = props.navigation.state.params;

  useEffect(() => {
    if (phoneRef && phoneRef.current) {
      setCountriesPickerData(phoneRef.current.getPickerData());
    }
  }, [phoneRef]);

  const onFBButtonPress = () => {
    authManager
      .loginOrSignUpWithFacebook(appConfig.appIdentifier)
      .then((response) => {
        if (response.user) {
          const user = response.user;
          props.setUserData({ user });
          props.navigation.navigate('MainStack', { user: user });
        } else {
          Alert.alert(
            '',
            localizedErrorMessage(response.error),
            [{ text: IMLocalized('OK') }],
            {
              cancelable: false,
            },
          );
        }
      });
  };

  const signInWithPhoneNumber = (userValidPhoneNumber) => {
    setLoading(true);
    authManager.onVerification(userValidPhoneNumber);
    authManager
      .sendSMSToPhoneNumber(userValidPhoneNumber, recaptchaVerifier.current)
      .then((response) => {
        const confirmationResult = response.confirmationResult;
        if (confirmationResult) {
          // SMS sent. Prompt user to type the code from the message, then sign the
          // user in with confirmationResult.confirm(code).
          window.confirmationResult = confirmationResult;
          setVerificationId(confirmationResult.verificationId);
          setIsPhoneVisible(false);
          setLoading(false);
        } else {
          // Error; SMS not sent
          setLoading(false);
          Alert.alert(
            '',
            localizedErrorMessage(response.error),
            [{ text: IMLocalized('OK') }],
            { cancelable: false },
          );
        }
      });
  };

  const signUpWithPhoneNumber = (smsCode) => {
    const userDetails = {
      firstName,
      lastName,
      phone: phoneNumber,
      photoURI: profilePictureURL,
    };
    setLoading(true);
    authManager
      .registerWithPhoneNumber(
        userDetails,
        smsCode,
        verificationId,
        appConfig.appIdentifier,
      )
      .then((response) => {
        if (response.error) {
          Alert.alert(
            '',
            localizedErrorMessage(response.error),
            [{ text: IMLocalized('OK') }],
            { cancelable: false },
          );
        } else {
          const user = response.user;
          props.setUserData({ user });
          props.navigation.navigate('MainStack', { user: user });
        }
        setLoading(false);
      });
  };

  const onPressSend = () => {
    if (phoneRef.current.isValidNumber()) {
      const userValidPhoneNumber = phoneRef.current.getValue();
      setLoading(true);
      setPhoneNumber(userValidPhoneNumber);
      if (!isSigningUp) {
        // If this is a login attempt, we first need to check that the user associated to this phone number exists
        authManager
          .retrieveUserByPhone(userValidPhoneNumber)
          .then((response) => {
            if (response.success) {
              signInWithPhoneNumber(userValidPhoneNumber);
            } else {
              setPhoneNumber(null);
              setLoading(false);
              Alert.alert(
                '',
                IMLocalized(
                  'You cannot log in. There is no account with this phone number.',
                ),
                [{ text: IMLocalized('OK') }],
                {
                  cancelable: false,
                },
              );
            }
          });
      } else {
        signInWithPhoneNumber(userValidPhoneNumber);
      }
    } else {
      Alert.alert(
        '',
        IMLocalized('Please enter a valid phone number.'),
        [{ text: IMLocalized('OK') }],
        {
          cancelable: false,
        },
      );
    }
  };

  const onPressFlag = () => {
    setCountryModalVisible(true);
  };

  const onPressCancelContryModalPicker = () => {
    setCountryModalVisible(false);
  };

  const onFinishCheckingCode = (newCode) => {
    setLoading(true);
    if (isSigningUp) {
      signUpWithPhoneNumber(newCode);
    } else {
      authManager.loginWithSMSCode(newCode, verificationId).then((response) => {
        if (response.error) {
          Alert.alert(
            '',
            localizedErrorMessage(response.error),
            [{ text: IMLocalized('OK') }],
            { cancelable: false },
          );
        } else {
          const user = response.user;
          props.setUserData({ user });
          props.navigation.navigate('MainStack', { user: user });
        }
        setLoading(false);
      });
    }
  };

  const phoneInputRender = () => {
    return (
      <>
        <PhoneInput
          style={styles.InputContainer}
          flagStyle={styles.flagStyle}
          textStyle={styles.phoneInputTextStyle}
          ref={phoneRef}
          onPressFlag={onPressFlag}
          offset={10}
          allowZeroAfterCountryCode
          textProps={{
            placeholder: IMLocalized('Phone number'),
            placeholderTextColor: '#aaaaaa',
          }}
        />
        {countriesPickerData && (
          <CountriesModalPicker
            data={countriesPickerData}
            appStyles={appStyles}
            onChange={(country) => {
              selectCountry(country);
            }}
            cancelText={IMLocalized('Cancel')}
            visible={countryModalVisible}
            onCancel={onPressCancelContryModalPicker}
          />
        )}
        <Button
          containerStyle={styles.sendContainer}
          style={styles.sendText}
          onPress={() => onPressSend()}>
          {IMLocalized('Send code')}
        </Button>
      </>
    );
  };

  const codeInputRender = () => {
    return (
      <>
        <CodeField
          ref={myCodeInput}
          inputPosition="full-width"
          variant="border-b"
          codeLength={6}
          size={50}
          space={8}
          keyboardType="numeric"
          cellProps={{ style: styles.input }}
          containerProps={{ style: styles.codeFieldContainer }}
          onFulfill={onFinishCheckingCode}
        />
      </>
    );
  };

  const selectCountry = (country) => {
    phoneRef.current.selectCountry(country.iso2);
  };

  const renderAsSignUpState = () => {
    return (
      <>
        <Text style={styles.title}>{IMLocalized('Create new account')}</Text>
        <TNProfilePictureSelector
          setProfilePictureURL={setProfilePictureURL}
          appStyles={appStyles}
        />

        <TextInput
          style={styles.InputContainer}
          placeholder={IMLocalized('First Name')}
          placeholderTextColor="#aaaaaa"
          onChangeText={(text) => setFirstName(text)}
          value={firstName}
          underlineColorAndroid="transparent"
        />

        <TextInput
          style={styles.InputContainer}
          placeholder={IMLocalized('Last Name')}
          placeholderTextColor="#aaaaaa"
          onChangeText={(text) => setLastName(text)}
          value={lastName}
          underlineColorAndroid="transparent"
        />
        {isPhoneVisible ? phoneInputRender() : codeInputRender()}
        <Text style={styles.orTextStyle}> {IMLocalized('OR')}</Text>
        <Button
          containerStyle={styles.signWithEmailContainer}
          onPress={() =>
            props.navigation.navigate('Signup', { appStyles, appConfig })
          }>
          {IMLocalized('Sign up with E-mail')}
        </Button>
      </>
    );
  };

  const renderAsLoginState = () => {
    return (
      <>
        <Text style={styles.title}>{IMLocalized('Sign In')}</Text>
        {isPhoneVisible ? phoneInputRender() : codeInputRender()}
        <Text style={styles.orTextStyle}> {IMLocalized('OR')}</Text>
        <Button
          containerStyle={styles.facebookContainer}
          style={styles.facebookText}
          onPress={() => onFBButtonPress()}>
          {IMLocalized('Login With Facebook')}
        </Button>
        <Button
          containerStyle={styles.signWithEmailContainer}
          onPress={() =>
            props.navigation.navigate('Login', { appStyles, appConfig })
          }>
          {IMLocalized('Sign in with E-mail')}
        </Button>
      </>
    );
  };

  return (
    <View style={styles.container}>
      <KeyboardAwareScrollView
        style={{ flex: 1, width: '100%' }}
        keyboardShouldPersistTaps="always">
        <TouchableOpacity onPress={() => props.navigation.goBack()}>
          <Image
            style={appStyles.styleSet.backArrowStyle}
            source={appStyles.iconSet.backArrow}
          />
        </TouchableOpacity>
        {isSigningUp ? renderAsSignUpState() : renderAsLoginState()}
        {isSigningUp && (
          <TermsOfUseView tosLink={appConfig.tosLink} style={styles.tos} />
        )}
        <FirebaseRecaptchaVerifierModal
          ref={recaptchaVerifier}
          firebaseConfig={firebaseConfig}
        />
      </KeyboardAwareScrollView>
      {loading && <TNActivityIndicator appStyles={appStyles} />}
    </View>
  );
};

export default connect(null, {
  setUserData,
})(SmsAuthenticationScreen);

升级到最新版本的React Native之后,我收到以下错误和堆栈:

错误:元素类型无效:预期为字符串(对于内置组件)或类/函数(对于复合组件),但得到:未定义。您可能忘记了从定义文件中导出组件,或者您可能混淆了默认导入和命名导入。

检查SmsAuthenticationScreen的呈现方法。

This error is located at:
    in RCTView (at View.js:34)
    in View (at ScrollView.js:1124)
    in RCTScrollView (at ScrollView.js:1260)
    in ScrollView (at ScrollView.js:1286)
    in ScrollView (at KeyboardAwareHOC.js:517)
    in KeyboardAwareScrollView (at SmsAuthenticationScreen.js:340)
    in RCTView (at View.js:34)
    in View (at SmsAuthenticationScreen.js:339)
    in SmsAuthenticationScreen (created by ConnectFunction)
    in ConnectFunction (created by SceneView)
    in SceneView (created by CardContainer)
    in RCTView (at View.js:34)
    in View (created by CardContainer)
    in RCTView (at View.js:34)
    in View (created by CardContainer)
    in RCTView (at View.js:34)
    in View (created by ForwardRef(CardSheet))
    in ForwardRef(CardSheet) (created by Card)
    in RCTView (at View.js:34)
    in View (at createAnimatedComponent.js:165)
    in AnimatedComponent (at createAnimatedComponent.js:215)
    in ForwardRef(AnimatedComponentWrapper) (created by PanGestureHandler)
    in PanGestureHandler (created by PanGestureHandler)
    in PanGestureHandler (created by Card)
    in RCTView (at View.js:34)
    in View (at createAnimatedComponent.js:165)
    in AnimatedComponent (at createAnimatedComponent.js:215)
    in ForwardRef(AnimatedComponentWrapper) (created by Card)
    in RCTView (at View.js:34)
    in View (created by Card)
    in Card (created by CardContainer)
    in CardContainer (created by Context.Consumer)
    in RNSScreen (at createAnimatedComponent.js:165)
    in AnimatedComponent (at createAnimatedComponent.js:215)
    in ForwardRef(AnimatedComponentWrapper) (at src/index.native.js:111)
    in Screen (created by MaybeScreen)
    in MaybeScreen (created by Context.Consumer)
    in RNSScreenContainer (at src/index.native.js:136)
    in ScreenContainer (created by MaybeScreenContainer)
    in MaybeScreenContainer (created by Context.Consumer)
    in CardStack (created by KeyboardManager)
    in KeyboardManager (created by Context.Consumer)
    in RNCSafeAreaProvider (at SafeAreaContext.tsx:74)
    in SafeAreaProvider (created by Context.Consumer)
    in SafeAreaProviderCompat (created by StackView)
    in GestureHandlerRootView (at GestureHandlerRootView.android.js:31)
    in GestureHandlerRootView (created by StackView)
    in StackView (created by StackView)
    in StackView
    in Unknown (created by Navigator)
    in Navigator (created by SceneView)
    in SceneView (created by SwitchView)
    in SwitchView (created by Navigator)
    in Navigator (at create-redux-container.js:93)
    in NavigatorReduxWrapper (created by ConnectFunction)
    in ConnectFunction (at App.js:48)
    in RCTView (at View.js:34)
    in View (created by MenuProvider)
    in RCTView (at View.js:34)
    in View (created by MenuProvider)
    in MenuProvider (at App.js:47)
    in RCTView (at View.js:34)
    in View (at NativeAppearance.tsx:4)
    in FallbackAppearanceProvider (at src/index.tsx:70)
    in AppearanceProvider (at App.js:46)
    in Provider (at App.js:45)
    in App (at renderApplication.js:45)
    in RCTView (at View.js:34)
    in View (at AppContainer.js:106)
    in RCTView (at View.js:34)
    in View (at AppContainer.js:132)
    in AppContainer (at renderApplication.js:39)

我已经尝试了其他文章和stackoverflow请求所提到的内容,但到目前为止还没有运气。这是React Native的新功能,因此可能会缺少一些简单的东西。

错误的另一个排列:

    ERROR    Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or 
you might have mixed up default and named imports.

Check the render method of `SmsAuthenticationScreen`.

This error is located at:
    in RCTView (at View.js:34)
    in View (at SmsAuthenticationScreen.js:339)
    in SmsAuthenticationScreen (created by ConnectFunction)
    in ConnectFunction (created by SceneView)
    in SceneView (created by CardContainer)
    in RCTView (at View.js:34)
    in View (created by CardContainer)
    in RCTView (at View.js:34)
    in View (created by CardContainer)
    in RCTView (at View.js:34)
    in View (created by ForwardRef(CardSheet))
    in ForwardRef(CardSheet) (created by Card)
    in RCTView (at View.js:34)
    in View (at createAnimatedComponent.js:165)
    in AnimatedComponent (at createAnimatedComponent.js:215)
    in ForwardRef(AnimatedComponentWrapper) (created by PanGestureHandler)
    in PanGestureHandler (created by PanGestureHandler)
    in PanGestureHandler (created by Card)
    in RCTView (at View.js:34)
    in View (at createAnimatedComponent.js:165)
    in AnimatedComponent (at createAnimatedComponent.js:215)
    in ForwardRef(AnimatedComponentWrapper) (created by Card)
    in RCTView (at View.js:34)
    in View (created by Card)
    in Card (created by CardContainer)
    in CardContainer (created by Context.Consumer)
    in RNSScreen (at createAnimatedComponent.js:165)
    in AnimatedComponent (at createAnimatedComponent.js:215)
    in ForwardRef(AnimatedComponentWrapper) (at src/index.native.js:111)
    in Screen (created by MaybeScreen)
    in MaybeScreen (created by Context.Consumer)
    in RNSScreenContainer (at src/index.native.js:136)
    in ScreenContainer (created by MaybeScreenContainer)
    in MaybeScreenContainer (created by Context.Consumer)
    in CardStack (created by KeyboardManager)
    in KeyboardManager (created by Context.Consumer)
    in RNCSafeAreaProvider (at SafeAreaContext.tsx:74)
    in SafeAreaProvider (created by Context.Consumer)
    in SafeAreaProviderCompat (created by StackView)
    in GestureHandlerRootView (at GestureHandlerRootView.android.js:31)
    in GestureHandlerRootView (created by StackView)
    in StackView (created by StackView)
    in StackView
    in Unknown (created by Navigator)
    in Navigator (created by SceneView)
    in SceneView (created by SwitchView)
    in SwitchView (created by Navigator)
    in Navigator (at create-redux-container.js:93)
    in NavigatorReduxWrapper (created by ConnectFunction)
    in ConnectFunction (at App.js:48)
    in RCTView (at View.js:34)
    in View (created by MenuProvider)
    in RCTView (at View.js:34)
    in View (created by MenuProvider)
    in MenuProvider (at App.js:47)
    in RCTView (at View.js:34)
    in View (at NativeAppearance.tsx:4)
    in FallbackAppearanceProvider (at src/index.tsx:70)
    in AppearanceProvider (at App.js:46)
    in Provider (at App.js:45)
    in App (at renderApplication.js:45)
    in RCTView (at View.js:34)
    in View (at AppContainer.js:106)
    in RCTView (at View.js:34)
    in View (at AppContainer.js:132)
    in AppContainer (at renderApplication.js:39)

这是package.json

{
  "name": "MyApp",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "start": "react-native start",
    "prettier": "prettier --write '*.js' 'src/**/*.js'",
    "test": "jest",
    "lint": "eslint .",
    "android": " cd android && ./gradlew clean && cd .. && react-native run-android",
    "ios": "react-native run-ios"
  },
  "dependencies": {
    "@react-native-community/art": "^1.2.0",
    "@react-native-community/async-storage": "^1.12.0",
    "@react-native-community/cameraroll": "^4.0.0",
    "@react-native-community/geolocation": "^2.0.2",
    "@react-native-community/masked-view": "^0.1.10",
    "@react-native-firebase/app": "^6.7.1",
    "@react-native-firebase/auth": "^6.7.1",
    "@react-native-firebase/messaging": "^6.7.1",
    "@skele/components": "^1.0.0-alpha.40",
    "axios": "^0.19.0",
    "base-64": "^0.1.0",
    "crypto-js": "^3.1.9-1",
    "expo-av": "~8.0.0",
    "expo-blur": "^8.1.0",
    "expo-camera": "^8.0.0",
    "expo-constants": "~8.0.0",
    "expo-facebook": "~8.0.0",
    "expo-file-system": "^8.1.0",
    "expo-firebase-recaptcha": "^1.1.3",
    "expo-image-picker": "~8.0.1",
    "expo-localization": "~8.0.0",
    "expo-location": "~8.0.0",
    "expo-permissions": "^8.1.0",
    "firebase": "7.19.1",
    "formik": "^2.1.5",
    "i18n-js": "^3.7.1",
    "invert-color": "^2.0.0",
    "jest-haste-map": "^25.1.0",
    "jest-serializer": "^25.1.0",
    "jest-worker": "^25.1.0",
    "lodash": "^4.17.20",
    "lodash.isequal": "^4.5.0",
    "lodash.memoize": "^4.1.2",
    "mobx": "^5.14.0",
    "mobx-react": "^6.3.0",
    "moment": "^2.24.0",
    "oauth-1.0a": "^2.2.6",
    "react": "16.13.1",
    "react-native": "0.63.2",
    "react-native-actionsheet": "^2.4.2",
    "react-native-animatable": "^1.3.3",
    "react-native-app-intro-slider": "^3.0.0",
    "react-native-appearance": "~0.3.4",
    "react-native-autogrow-textinput": "^5.4.0",
    "react-native-button": "^3.0.1",
    "react-native-cli": "^2.0.1",
    "react-native-confirmation-code-field": "^6.5.0",
    "react-native-dialog-input": "^1.0.8",
    "react-native-fast-image": "^8.3.2",
    "react-native-fbsdk": "2.0.0",
    "react-native-geocoding": "^0.4.0",
    "react-native-gesture-handler": "^1.7.0",
    "react-native-get-random-values": "^1.4.0",
    "react-native-google-places-autocomplete": "^1.8.0",
    "react-native-image-crop-picker": "^0.32.3",
    "react-native-image-filter-kit": "^0.7.3",
    "react-native-image-picker": "^2.3.3",
    "react-native-image-progress": "^1.1.1",
    "react-native-image-view": "^2.1.9",
    "react-native-indicators": "^0.17.0",
    "react-native-iphone-x-helper": "^1.2.1",
    "react-native-keyboard-aware-scroll-view": "^0.9.2",
    "react-native-keyboard-aware-view": "0.0.14",
    "react-native-keyboard-input": "^6.0.0",
    "react-native-keyboard-tracking-view": "^5.6.1",
    "react-native-localize": "^1.4.1",
    "react-native-maps": "0.27.1",
    "react-native-modal": "^11.5.6",
    "react-native-modal-patch": "git+https://github.com/HarvestProfit/react-native-modal-patch.git",
    "react-native-modalbox": "^2.0.0",
    "react-native-phone-input": "^0.2.4",
    "react-native-popup-menu": "^0.15.9",
    "react-native-progress": "^4.1.2",
    "react-native-reanimated": "^1.2.0",
    "react-native-safe-area-context": "^3.1.7",
    "react-native-screens": "^2.10.1",
    "react-native-search-box": "0.0.19",
    "react-native-slider": "^0.11.0",
    "react-native-splash-screen": "^3.2.0",
    "react-native-swiper": "^1.6.0-nightly.5",
    "react-native-unimodules": "^0.10.1",
    "react-native-vector-icons": "7.0.0",
    "react-native-video": "^5.0.2",
    "react-native-view-more-text": "^2.1.0",
    "react-native-webview": "^10.8.2",
    "react-navigation": "^4.4.0",
    "react-navigation-drawer": "^2.5.0",
    "react-navigation-redux-helpers": "^4.0.1",
    "react-navigation-stack": "^2.8.2",
    "react-navigation-tabs": "^2.9.0",
    "react-redux": "^7.2.1",
    "redux": "^4.0.5",
    "redux-logger": "^3.0.6",
    "redux-thunk": "^2.3.0",
    "remote-redux-devtools": "^0.5.16",
    "uuidv4": "^5.0.1"
  },
  "devDependencies": {
    "@babel/core": "^7.11.4",
    "@babel/plugin-proposal-decorators": "^7.10.5",
    "@babel/runtime": "^7.8.4",
    "@react-native-community/eslint-config": "^1.1.0",
    "babel-jest": "^25.1.0",
    "babel-plugin-transform-remove-console": "^6.9.4",
    "eslint": "6.5.1",
    "jest": "^25.1.0",
    "metro-react-native-babel-preset": "^0.59.0",
    "prettier": "2.0.5",
    "react-test-renderer": "16.13.1"
  },
  "jest": {
    "preset": "react-native"
  }
}

3 个答案:

答案 0 :(得分:3)

如果仅升级本机版本,则可以快速清除缓存并重置模块:

rm -rf node_modules && yarn cache clean && yarn install

答案 1 :(得分:2)

从您的日志中,似乎由于KeyboardAwareScrollView模块而出现错误。快速搜索此模块的github存储库后,我发现了以下内容:https://github.com/APSL/react-native-keyboard-aware-scroll-view/issues/443

该问题仍未得到解决,但是上面的链接中提供了一些解决方法,您可以尝试这些方法。我只需卸载react-native-keyboard-aware-scroll-view并安装此fork即可解决此问题:

npm i @codler/react-native-keyboard-aware-scroll-view

答案 2 :(得分:1)

您为什么使用react-native-keyboard-aware-scroll-view

您可以在iOS中使用react-native-input-scroll-view,在Android中使用ScrollView

import InputScrollView from 'react-native-input-scroll-view';


       {Platform.OS === 'android' ? (
          <ScrollView>
            <View style={styles.subContainer}>{children}</View>
          </ScrollView>
        ) : (
          <InputScrollView>
            <View style={styles.subContainer}>{children}</View>
          </InputScrollView>
        )}
相关问题