Сбой преобразования компонента на основе класса в компонент на основе функций

#javascript #reactjs #react-native #function #class

Вопрос:

Я переключаюсь с компонента на основе классов на компоненты на основе функций, но мой код работает в компоненте на основе классов и не работает в компоненте на основе функций.

Вот код:

 import { connect } from "react-redux";
import * as actions from "../redux/actions/authActions";

class Login extends Component {
  constructor(props) {
    super(props);
    this.state = {
      email: "",
      password: "",
    };
  }

  authenticate() {
    this.props.auth(this.state.email, this.state.password).then((response) => {
      if (this.props.authenticated) {
        alert("User Is Authenticated");
      } else {
        alert("User Isn't Authenticated");
      }
    });
  }

  render() {
    return (
      <View style={{ flex: 1 }}>
        <TextInput
          autoCapitalize="none"
          keyboardType="email-address"
          style={// styles here}
          placeholder="Enter email"
          value={this.state.email}
          onChangeText={(email) => this.setState({ email })}
        />
        <TextInput
          autoCapitalize="none"
          secureTextEntry
          style={// styles here}
          placeholder="Enter password"
          value={this.state.password}
          onChangeText={(password) => this.setState({ password })}
        />
        <TouchableOpacity onPress={() => this.authenticate()}>
          <Text style={{ marginTop: 20, color: "black", textAlign: "center" }}>
            Login
          </Text>
        </TouchableOpacity>
      </View>
    );
  }
}

const mapStateToProps = (state) => ({
  isLoggedIn: state.auth.isLoggedIn,
  isLoading: state.auth.isLoading,
  userData: state.auth.userData,
  error: state.auth.error,
  authenticated: state.auth.isAuthenticated,
  mainState: state,
});

const mapDispatchToProps = (dispatch) => ({
  auth: (email, password) => dispatch(actions.loginUser({ email, password })),
});

export default connect(mapStateToProps, mapDispatchToProps)(Login);
 

Преобразованный код в компонент на основе функций

 import { connect } from "react-redux";
import * as actions from "../redux/actions/authActions";

function Login({ auth, authenticated }) {
  const [email, setEmail] = useState("");
  const [password, setPassword] = useState("");

  const authenticate = () => {
    auth(email, password).then((response) => {
      if (authenticated) {
        alert("User Is Authenticated");
      } else {
        alert("User Isn't Authenticated");
      }
    });
  };

  return (
    <View style={{ flex: 1 }}>
      <TextInput
        autoCapitalize="none"
        keyboardType="email-address"
        style={ // styles here}
        placeholder="Enter email"
        value={email}
        onChangeText={(text) => setEmail(text)}
      />
      <TextInput
        autoCapitalize="none"
        secureTextEntry
        style={ // styles here}
        placeholder="Enter password"
        value={password}
        onChangeText={(text) => setPassword(text)}
      />
      <TouchableOpacity onPress={() => authenticate()}>
        <Text style={{ marginTop: 20, color: "black", textAlign: "center" }}>
          Login
        </Text>
      </TouchableOpacity>
    </View>
  );
}

const mapStateToProps = (state) => ({
  isLoggedIn: state.auth.isLoggedIn,
  isLoading: state.auth.isLoading,
  userData: state.auth.userData,
  error: state.auth.error,
  authenticated: state.auth.isAuthenticated,
  mainState: state,
});

const mapDispatchToProps = (dispatch) => ({
  auth: (email, password) => dispatch(actions.loginUser({ email, password })),
});

export default connect(mapStateToProps, mapDispatchToProps)(Login);
 

Здесь, на Login приеме. Состояние приложения не обновляется в первый раз, но обновляется при последующих попытках.

Спасибо вам за чтение и помощь.

Комментарии:

1. при 2-м нажатии кнопки входа в систему это работает, но не при первом?

2. кнопка компонента функции работает как при первом, так и при втором щелчке, но при первом щелчке, даже если я вижу ответ от сервера, props.authenticated true он всегда отображается false в первый раз.

3. Код работает в компоненте, основанном на классе, но не работает в компоненте, основанном на функциях.

Ответ №1:

Вы закрыли устаревшее состояние из цикла рендеринга, в котором authenticate он был вызван. Обновления состояния реакции являются асинхронными, поэтому, если вы хотите обработать состояние после обновления, вам нужно сделать это в следующем цикле рендеринга, скорее всего, в useEffect hook (синоним метода компонента на основе классов componentDidUpdate ). Когда authenticated значение состояния redux обновляется, компонент перенаправляется повторно.

 useEffect(() => {
  if (authenticated) {
    alert("User Is Authenticated");
  } else {
    alert("User Isn't Authenticated");
  }
}, [authenticated]);

authenticate() {
  auth(email, password)
    .then((response) => {
      console.log(response);      
    });
}
 

Обновить

Этот useEffect обратный вызов будет отображать одно или другое предупреждение, каждый рендеринг. Вы можете добавить состояние, чтобы заставить его ждать, пока вы не отправите запрос на аутентификацию и не пройдете проверку подлинности.

 const [isAuthenticating, setIsAuthenticating] = useState(false);
const [finishedAuth, setFinishedAuth] = useState(false);

useEffect(() => {
  if (isAuthenticating amp;amp; finishedAuth) {
    alert(authenticated
      ? "User Is Authenticated"
      : "User Isn't Authenticated"
    );
  }
}, [isAuthenticating, finishedAuth, authenticated]);

authenticate() {
  setIsAuthenticating(true);
  auth(email, password)
    .then((response) => {
      console.log(response);
    })
    .finally(() => setFinishedAuth(true));
}
 

Кстати, эти два дополнительных состояния могут быть отличными кандидатами для хранения в вашем состоянии redux.

Комментарии:

1. Спасибо, кажется, я близок, но здесь, когда я перехожу на экран входа в систему, мгновенно появляется вышеупомянутое предупреждение «Пользователь не аутентифицирован». Несмотря на то, что я ничего не ввел в поле электронной почты и пароля и не отправлял форму.

2. Теперь все работает так, как ожидалось, большое вам спасибо. Как мне решить это начальное всплывающее окно?

3. @NoorNoori Вы можете добавить дополнительные условия, такие как не вызывать при первоначальном рендеринге, или проверить, что электронная почта и пароль соответствуют действительности, или, возможно, просто добавить дополнительное состояние, которое вы запускаете при аутентификации, т. е. «отправил запрос на аутентификацию» и «прошел аутентификацию».

4. не могли бы вы обновить ответ, почему он показывает всплывающее окно по умолчанию? спасибо за помощь

5. привет @DrewReese, я пытался создать аналогичное приложение, и, похоже, я не сталкивался с такой ошибкой. Я получаю значения непосредственно при первом щелчке мыши. не могли бы вы, пожалуйста, помочь мне понять ваш ответ и почему мое приложение также нормально работает при первом щелчке мыши? Спасибо. codesandbox.io/s/red-cdn-eg66n?file=/src/App.js