Нарушение инварианта: недопустимый тип элемента: ожидал строку или класс / функцию, но получил неопределенный - PullRequest
0 голосов
/ 03 марта 2019

Я искал и реализовывал все, что мог найти в его ошибке весь день, если быть точным, 12 часов.Я застрял, и я попытался восстановить свое приложение, реагирующее на нативное.Я действительно до последней капли здесь.Я знаю, что на это ответили другие, но я попробовал самый популярный ответ на эту проблему, но безуспешно.Я построил свое приложение, используя EXPO INIT.Вот мой код, файл package.json и полученная ошибка. У меня есть несколько общих файлов, которые являются функциональными компонентами.Если я закомментирую TextFieldGroup на моей странице SignUp, он просто выдаст ошибку следующему функциональному компоненту CalendarFieldGroup Когда я нажимаю кнопку «Зарегистрироваться» на моей домашней странице, он возвращает экран ошибок.Я также выложу свой файл App.js.

// Not all of the code, just what is needed to help diagnose the problem hopefully
import { Provider } from 'react-redux';
import store from './store';

import LoginOrSignUp from './src/components/auth/LoginOrSignUp';
import Register from './src/components/auth/SignUp';
import Login from './src/components/auth/Login';

class App extends Component {
  render() {
    return (
      <Provider store={store}>
        <NativeRouter>
          <View style={styles.container}>
            <Switch>
              {/*Public Routes*/}
              <Route exact path="/login-or-sign-up" component={LoginOrSignUp} />
              <Route exact path="/sign-up" component={Register} />
              <Route exact path="/login" component={Login} />
              <Route

import React, { Component } from 'react';
import { Text, View, TouchableOpacity, StyleSheet } from 'react-native';
import PropTypes from 'prop-types';

import { withRouter, Link } from 'react-router-native';
import { connect } from 'react-redux';
import moment from 'moment';

import { registerUser } from '../../actions/authActions';
import { clearErrors } from '../../actions/errorActions';

import BackButton from '../common/BackButton';
import Spinner from '../common/Spinner';
import TextFieldGroup from '../common/TextFieldGroup';
import CalendarFieldGroup from '../common/CalendarFieldGroup';
import SelectButtonGroup from '../common/SelectButtonGroup';

class SignUp extends Component {
  state = {
    firstName: '',
    lastName: '',
    email: '',
    password: '',
    password2: '',
    location: '',
    dateOfBirth: '',
    sex: '',
    selectedIndex: -1,
    errors: {}
  };

  componentDidMount() {
    if (this.props.auth.isAuthenticated) {
      this.props.history.push('/');
    }
    if (this.props.errors) {
      this.props.clearErrors();
    }
  }

  static getDerivedStateFromProps(nextProps) {
    if (nextProps.errors) {
      return { errors: nextProps.errors };
    }
    return null;
  }

  componentDidUpdate(prevProps) {
    if (prevProps.errors !== this.props.errors) {
      this.setState({ errors: this.props.errors });
    }
  }

  onChangeText = (text, field) => {
    this.setState({
      [field]: text
    });
  };

  onDateChange = (newDate, field) => {
    this.setState({
      [field]: newDate
    });
  };

  updateIndex = selectedIndex => {
    const sex = selectedIndex === 0 ? 'male' : 'female';
    this.setState({
      sex,
      selectedIndex
    });
  };

  onSubmit = e => {
    e.preventDefault();
    const newUser = {
      firstName: this.state.firstName,
      lastName: this.state.lastName,
      email: this.state.email.toLowerCase(),
      password: this.state.password,
      password2: this.state.password2,
      dateOfBirth: this.state.dateOfBirth,
      location: this.state.location,
      sex: this.state.sex
    };

    this.props.registerUser(newUser, this.props.history);
  };

  render() {
    const { errors } = this.state;
    const { loading } = this.props.auth;
    const dob = moment(
      new Date(this.state.dateOfBirth),
      'MMMM Do YYYY, h:mm:ss a'
    ).format('MMMM Do YYYY');

    let signUpContent;

    if (loading) {
      signUpContent = <Spinner />;
    } else {
      signUpContent = (
        <View style={styles.container}>
          <BackButton to="/login-or-sign-up" />
          <Text style={styles.signup}>Create an Account</Text>
          <Text style={styles.time}>Find Time To Live Life</Text>
          <View>
            <TextFieldGroup
              label="First Name"
              placeholder="Please enter your first name..."
              name="firstName"
              type="text"
              value={this.state.firstName}
              onChangeText={text => this.onChangeText(text, 'firstName')}
              error={errors.firstName}
            />

            <TextFieldGroup
              label="Last Name"
              placeholder="Please enter your last name..."
              name="lastName"
              type="text"
              value={this.state.lastName}
              onChangeText={text => this.onChangeText(text, 'lastName')}
              error={errors.lastName}
            />

            <TextFieldGroup
              label="Email Address"
              placeholder="Please enter your email address..."
              name="email"
              type="email"
              value={this.state.email}
              onChangeText={text => this.onChangeText(text, 'email')}
              error={errors.email}
            />

            <TextFieldGroup
              label="Location"
              placeholder="Please enter your current location..."
              name="location"
              type="text"
              value={this.state.location}
              onChangeText={text => this.onChangeText(text, 'location')}
              error={errors.location}
            />

            <TextFieldGroup
              label="Password"
              placeholder="Please enter a password..."
              name="password"
              type="password"
              secureTextEntry={true}
              value={this.state.password}
              onChangeText={text => this.onChangeText(text, 'password')}
              error={errors.password}
            />

            <TextFieldGroup
              label="Confirm Password"
              placeholder="Please re-enter your password..."
              name="password2"
              type="password"
              secureTextEntry={true}
              value={this.state.password2}
              onChangeText={text => this.onChangeText(text, 'password2')}
              error={errors.password2}
            />

            <View style={styles.calendar}>
              <CalendarFieldGroup
                label="Date of Birth"
                date={this.state.dateOfBirth}
                placeholder="Please enter your birthdate..."
                onDateChange={date => this.onDateChange(date, 'dateOfBirth')}
                error={errors.dateOfBirth}
              />
              <Text>
                {dob !== 'Invalid date'
                  ? dob
                  : 'Please enter your birth date...'}
              </Text>
            </View>

            <SelectButtonGroup
              label="Please select your gender..."
              onPress={this.updateIndex}
              selectedIndex={this.state.selectedIndex}
              buttons={['Male', 'Female']}
              error={errors.sex}
            />

            <TouchableOpacity onPress={this.onSubmit} style={styles.btn}>
              <Text>Sign Up</Text>
            </TouchableOpacity>

            <Link to="/terms-of-service">
              <Text style={styles.terms}>
                Terms of Service &amp; Privacy Policy
              </Text>
            </Link>
          </View>
        </View>
      );
    }
    return <View>{signUpContent}</View>;
  }
}

const styles = StyleSheet.create({
  container: {},
  signup: {
    fontSize: 20,
    color: 'blue',
    margin: 5,
    marginLeft: 'auto',
    marginRight: 'auto'
  },
  time: {
    fontSize: 12,
    color: 'grey',
    margin: 5,
    marginLeft: 'auto',
    marginRight: 'auto'
  },
  calendar: {
    marginLeft: 'auto',
    marginRight: 'auto'
  },
  btn: {
    alignItems: 'center',
    backgroundColor: '#DDDDDD',
    padding: 10,
    marginTop: 10
  },
  terms: {
    color: 'grey',
    fontSize: 10,
    marginTop: 5,
    marginLeft: 'auto',
    marginRight: 'auto'
  }
});

SignUp.propTypes = {
  registerUser: PropTypes.func.isRequired,
  clearErrors: PropTypes.func.isRequired,
  auth: PropTypes.object.isRequired,
  errors: PropTypes.object.isRequired
};

const mapStateToProps = state => ({
  auth: state.auth,
  errors: state.errors
});

export default connect(
  mapStateToProps,
  { registerUser, clearErrors }
)(withRouter(SignUp));

import React, { Component } from 'react';
import { Text, View, TouchableOpacity, StyleSheet } from 'react-native';
import PropTypes from 'prop-types';

import { Link } from 'react-router-native';
import { connect } from 'react-redux';

import { loginUser, clearUserEmail } from '../../actions/authActions';
import { clearErrors } from '../../actions/errorActions';

import BackButton from '../common/BackButton';
import Spinner from '../common/Spinner';
import TextFieldGroup from '../common/TextFieldGroup';

class Login extends Component {
  state = {
    email: '',
    password: '',
    errors: {}
  };

  componentDidMount() {
    if (this.props.auth.isAuthenticated) {
      this.props.history.push('/');
    }
    if (this.props.errors) {
      this.props.clearErrors();
    }
    if (this.props.auth.email) {
      this.props.clearUserEmail();
    }
  }

  static getDerivedStateFromProps(nextProps, prevState) {
    if (nextProps.errors) {
      return { errors: nextProps.errors };
    }
    return null;
  }

  componentDidUpdate(prevProps, prevState) {
    if (prevProps.errors !== this.props.errors) {
      this.setState({
        errors: this.props.errors
      });
    }
    if (this.props.auth.isAuthenticated) {
      this.setState({ isAuthenticated: this.props.auth.isAuthenticated });
      this.props.history.push('/');
    }
    if (this.props.errors.email === 'You must confirm your email') {
      this.props.history.push('/email-confirmation-email');
    }
  }

  onChangeText = (text, field) => {
    this.setState({
      [field]: text
    });
  };

  onSubmit = e => {
    e.preventDefault();

    const userData = {
      email: this.state.email.toLowerCase(),
      password: this.state.password
    };

    this.props.loginUser(userData);
  };

  render() {
    const { errors } = this.state;
    const { loading } = this.props.auth;

    let loginContent;

    if (loading) {
      loginContent = <Spinner />;
    } else {
      loginContent = (
        <View style={styles.container}>
          <BackButton to="/login-or-sign-up" />
          <Text style={styles.login}>Login</Text>
          <Text style={styles.time}>Find time to Hang Out</Text>

          <TextFieldGroup
            label="Email Address"
            placeholder="Please enter your email address..."
            name="email"
            type="email"
            value={this.state.email}
            onChangeText={text => this.onChangeText(text, 'email')}
            error={errors.email}
          />

          <TextFieldGroup
            label="Password"
            placeholder="Please enter a password..."
            name="password"
            type="password"
            secureTextEntry={true}
            value={this.state.password}
            onChangeText={text => this.onChangeText(text, 'password')}
            error={errors.password}
          />

          <TouchableOpacity onPress={this.onSubmit} style={styles.btn}>
            <Text style={styles.time}>Login</Text>
          </TouchableOpacity>

          <View style={styles.forgotPassword}>
            <Link to="/forgot-password-email">
              <Text style={styles.forgotPassowrdText}>forgot password?</Text>
            </Link>
          </View>
        </View>
      );
    }

    return <View>{loginContent}</View>;
  }
}

const styles = StyleSheet.create({
  container: {},
  login: {
    fontSize: 20,
    color: 'blue',
    marginLeft: 'auto',
    marginRight: 'auto'
  },
  time: {
    fontSize: 12,
    color: 'grey',
    margin: 5,
    marginLeft: 'auto',
    marginRight: 'auto'
  },
  btn: {
    alignItems: 'center',
    backgroundColor: '#DDDDDD',
    padding: 10,
    marginTop: 10
  },
  forgotPassword: {
    height: 16,
    marginTop: 100,
    marginLeft: 'auto',
    marginRight: 'auto'
  },
  forgotPassowrdText: {
    fontSize: 12,
    color: '#d15555'
  }
});

Login.propTypes = {
  loginUser: PropTypes.func.isRequired,
  auth: PropTypes.object.isRequired,
  errors: PropTypes.object.isRequired
};

const mapStateToProps = state => ({
  auth: state.auth,
  errors: state.errors
});

export default connect(
  mapStateToProps,
  { loginUser, clearErrors, clearUserEmail }
)(Login);

import React from 'react';
import { Text, View, StyleSheet } from 'react-native';
import PropTypes from 'prop-types';

import { FormLabel, FormInput } from 'react-native-elements';

const TextFieldGroup = ({
  label,
  type,
  secureTextEntry,
  placeholder,
  name,
  value,
  onChangeText,
  disabled,
  info,
  error
}) => {
  return (
    <View style={styles.formGroup}>
      {error ? (
        <View>
          <FormLabel>
            {label} <Text style={styles.error}>{error}</Text>
          </FormLabel>
        </View>
      ) : (
        <FormLabel>{label}</FormLabel>
      )}

      <FormInput
        type={type}
        secureTextEntry={secureTextEntry}
        placeholder={placeholder}
        name={name}
        value={value}
        onChangeText={onChangeText}
        disabled={disabled}
      />
      {info && <Text style={styles.info}>{info}</Text>}
    </View>
  );
};

const styles = StyleSheet.create({
  formGroup: {},
  info: {},
  error: {
    fontSize: 8,
    color: 'red'
  }
});

TextFieldGroup.propTypes = {
  label: PropTypes.string,
  type: PropTypes.string.isRequired,
  secureTextEntry: PropTypes.bool,
  placeholder: PropTypes.string,
  name: PropTypes.string.isRequired,
  value: PropTypes.string.isRequired,
  onChangeText: PropTypes.func.isRequired,
  disabled: PropTypes.string,
  info: PropTypes.string,
  error: PropTypes.string
};

TextFieldGroup.defaultProps = {
  type: 'text',
  value: '',
  secureTextEntry: false
};

export default TextFieldGroup;

{
  "main": "node_modules/expo/AppEntry.js",
  "scripts": {
    "start": "expo start",
    "android": "expo start --android",
    "ios": "expo start --ios",
    "eject": "expo eject"
  },
  "dependencies": {
    "axios": "^0.18.0",
    "expo": "^32.0.0",
    "jwt-decode": "^2.2.0",
    "moment": "^2.24.0",
    "react": "16.5.0",
    "react-moment": "^0.8.4",
    "react-native": "https://github.com/expo/react-native/archive/sdk-32.0.0.tar.gz",
    "react-native-datepicker": "^1.7.2",
    "react-native-elements": "^1.1.0",
    "react-native-scripts": "^2.0.1",
    "react-native-vector-icons": "^6.3.0",
    "react-redux": "^6.0.1",
    "react-router-native": "^4.3.0",
    "redux": "^4.0.1",
    "redux-thunk": "^2.3.0"
  },
  "devDependencies": {
    "babel-preset-expo": "^5.0.0"
  },
  "private": true
}

Ответы [ 2 ]

0 голосов
/ 03 марта 2019

Так что я просто все понял.Пакет response-native-elements@1.1.0 давал мне ошибку.Я откатился до версии response-native-elements@0.19.1.Они обновили свой пакет 6 дней назад, и я не работал над моим проектом в течение 7 дней.Я думаю, что обновил пакет, когда начал работать этим утром, до самой последней версии и бум, хаос!

0 голосов
/ 03 марта 2019

Чтобы использовать TextFieldGroup так же, как вы используете сейчас, вам нужно сделать его class, который простирается от React.Component.ИМО, это было бы идеальным решением

export default class TextFieldGroup extends React.Component {
  render() {
    ...
  }
}

Если вы хотите использовать его как функцию, вы можете

export const createTextFieldGroup = ({
  label,
  type,
  secureTextEntry,
  placeholder,
  name,
  value,
  onChangeText,
  disabled,
  info,
  error
}) => {
  return (
    ...
  )
}

и затем вызывать его следующим образом:

import {createTextFieldGroup} from '../common/TextFieldGroup`;

...

render() {
  <View>
    {
      createTextFieldGroup({
        label: "First Name"
        placeholder: "Please enter your first name..."
        name: "firstName"
        type: "text"
        value: this.state.firstName
        onChangeText: text => this.onChangeText(text, 'firstName')
        error: errors.firstName
      })
    }
  </View>
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...