#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