Я вставил все, что есть, в этом коде очень небольшая проблема, но я не могу ее решить. Просмотрите этот код.
При утешении отображается следующая ошибка:
Uncaught TypeError: Cannot read property 'state' of undefined reactjs
Код:
export class Login extends Component {
constructor(props) {
super(props);
this.handleChangeEventforSignUp = this.handleChangeEventforSignUp.bind(this);
this.createNewUserWithEmailPassword = this.createNewUserWithEmailPassword.bind(this);
this.state = {
sign_up_details: {
email: "",
password: "",
confirmpassword: "",
notification: ""
}
};
}
createNewUserWithEmailPassword(event){
event.preventDefault();
if ((this.state.sign_up_details.password !== "") && (this.state.sign_up_details.confirmpassword !== "")){
if (this.state.sign_up_details.password === this.state.sign_up_details.confirmpassword){
let updateNotification = Object.assign({}, this.state.sign_up_details, {notification: "Password matched"});
this.setState({
sign_up_details: updateNotification
});
app.auth().createUserWithEmailAndPassword(this.state.sign_up_details.email, this.state.sign_up_details.password)
.catch(function(error) {
// Handle Errors here.
let errorCode = error.code;
console.info(errorCode);
let errorMessage = error.message;
if (errorCode == 'auth/weak-password') {
let notify = Object.assign({}, this.state.sign_up_details, {notification: errorMessage});
this.setState({
sign_up_details: notify
});
} else {
// alert(errorMessage);
let notify = Object.assign({}, this.state.sign_up_details, {notification: errorMessage});
this.setState({
sign_up_details: notify
},
() => {
console.info(this.state.sign_up_details);
} );
}
console.info(error);
}).then(
function(onResolve, onReject){
console.info(onResolve);
console.info(onReject);
}
);
}else{
let notify = Object.assign({}, this.state.sign_up_details, {notification: "Password not matched"});
this.setState({
sign_up_details: notify
});
}
}
}
handleChangeEventforSignUp(event){
// console.info(event);
const target = event.target;
let emailInput = "";
let passwordInput = "";
let confirmpasswordInput = "";
if (target.type === 'email'){
emailInput = target.value;
let updateEmail = Object.assign({}, this.state.sign_up_details, {email: emailInput});
this.setState({
sign_up_details: updateEmail
});
}
if (target.type === 'password' && target.name === 'password'){
passwordInput = target.value;
let updatePassword = Object.assign({}, this.state.sign_up_details, {password: passwordInput});
this.setState({
sign_up_details: updatePassword
});
}
if (target.type === 'password' && target.name === 'confirmpassword'){
confirmpasswordInput = target.value;
let updateConfirmpassword = Object.assign({}, this.state.sign_up_details, {confirmpassword: confirmpasswordInput});
this.setState({
sign_up_details: updateConfirmpassword
});
}
}
render() {
const { from } = this.props.location.state || { from: { pathname: '/' } }
// const { from } = this.props.history.location || { from: { pathname: '/' } }
if (this.state.redirect === true) {
return <Redirect to = {from} />
}
return (
<div id = "register" class = "container tab-pane fade animated fadeIn">
<form onSubmit = {this.createNewUserWithEmailPassword} className = "formfield" ref = {(form) => { this.signupForm = form }} method = "post">
<h1 className = "text-center login-heading pt-2 pb-4"><i className = "fa fa-pencil fa-lg mx-2" ></i> Register</h1>
{/* <input value = {this.state.sign_up_details.name} onChange = {this.handleChangeEventforSignUp} className = "form-control input mb-2" name = "name" type = "text" placeholder = "John Doe" /> */}
<input value = {this.state.sign_up_details.email} onChange = {this.handleChangeEventforSignUp} className = "form-control input mb-2" name = "email" type = "email" placeholder = "[email protected]" />
<input value = {this.state.sign_up_details.password} onChange = {this.handleChangeEventforSignUp} className = "form-control input mb-2" name = "password" type = "password" placeholder = "*******" />
<input value = {this.state.sign_up_details.confirmpassword} onChange = {this.handleChangeEventforSignUp} className = "form-control input mb-2" name = "confirmpassword" type = "password" placeholder = "*******" />
<p className = "text_ter text_pink">{this.state.sign_up_details.notification !== "" ? this.state.sign_up_details.notification : ""}</p>
<input type = "submit" className = "btn btn-primary btn-sm btn-block p-2 mt-4 mb-2" value = "Log In"></input>
</form>
</div>
)
}
}
ReactDOM.render(<Login/>, document.getElementById('app'));<script src = "https://cdnjs.cloudflare.com/ajax/libs/react/15.0.0/react.min.js"></script>
<script src = "https://cdnjs.cloudflare.com/ajax/libs/react/15.0.0/react-dom.min.js"></script>
<div id = "app"><div>Находясь внутри catch, ваш this не ссылается на класс компонента, поэтому он не имеет никакого состояния. Вы должны объявить его вне асинхронного запроса, например, let self = this.state, а затем использовать его.
отметьте этот ответ Как сделать setState внутри обратного вызова
Консоль показывает ошибку на else { // alert(errorMessage); let notify = Object.assign({}, this.state.sign_up_details, {notification: errorMessage}); this.setState({ sign_up_details: notify }, () => { console.info(this.state.sign_up_details); } ); в этом блоке код
@Ionut Спасибо, пытаюсь
Пожалуйста, прочтите При каких обстоятельствах я могу добавить к своему вопросу «срочно» или другие похожие фразы, чтобы получить более быстрые ответы? - вкратце, это не идеальный способ обращения к волонтерам и, вероятно, контрпродуктивно для получения ответов. Пожалуйста, воздержитесь от добавления этого к своим вопросам.
Спасибо всем гикам, проблема заключалась в обещаниях. Я использовал традиционные функции js вместо функций стрелок ES7. Я просто использовал функцию стрелок вместо функций js в обратном вызове обещаний, все решено.
app.auth().createUserWithEmailAndPassword(this.state.sign_up_details.email, this.state.sign_up_details.password).catch((error) => {let errorCode = error.code; if (errorCode == 'auth/weak-password') {weakPass = error.message;let notify = Object.assign({}, this.state.sign_up_details, {notification: weakPass}); this.setState({sign_up_details: notify});} else {genericError = error.message;let notify = Object.assign({}, this.state.sign_up_details, {notification: genericError});this.setState({sign_up_details: notify});}


![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Кажется, вы используете реактивный маршрутизатор (который дает вам, например, компонент Redirect), но он никогда не импортируется и не включается нигде?
Извините, но перенаправление не является частью этой ошибки. Что-то не так с this.state.signup_details. Это всего лишь фрагмент кода полного приложения. @timotgl
Могу ли я установить состояние конкретного класса в обещаниях? @timotgl
@kropani Попробуйте изменить методы так, чтобы они включали компонент в this.: createNewUserWithEmailPassword = (event) => {} То же самое для других методов.
Таким образом, эта ошибка эквивалентна написанию undefined.state.
Взгляните на свои обработчики событий, такие как handleChangeEventForSignup(), которые вы неправильно используете в именовании, это не совсем верблюжий случай, у вас есть handleChangeEventforSignup().
Конкретно в отношении этой ошибки, посмотрите на createNewUserWithEmailPassword().
Вы пытались сначала протестировать это, выполнив:
createNewUserWithEmailPassword(event) {
event.preventDefault();
console.info(this.state.sign_up_details);
}
Вы видите здесь другую проблему? Опять же, соглашение об именах. Вам нужен этот обработчик событий, чтобы делать что-то одно за раз. Вы видите, что добавленный мной консольный журнал не работает? Он будет проверять только электронную почту, но если бы вы сделали это в первую очередь, вы знаете, что делайте это шаг за шагом и тестируйте свой код по ходу дела, вы, вероятно, получили бы эту ошибку раньше.
JavaScript считает, что внутри вашего createNewUserWithEmailPassword() не равно this, а вместо этого this равно undefined.
Вам необходимо проверить, для чего ключевое слово this используется внутри класса и как значение this определяется внутри функции.
Ваш экземпляр Login должен иметь несколько различных свойств, таких как state, render() и createNewUserWithEmailPassword().
Вы должны иметь возможность ссылаться на ключевое слово this, которое является ссылкой на сам класс.
Итак, вы говорите, дайте мне ссылку на экземпляр Login, внутри которого я пишу код. Это должно дать вам доступ к state, render() и createNewUserWithEmailPassword().
Я бы очистил код примерно так:
class Login extends React.Component {
state = {
sign_up_details: {
email: "",
password: "",
confirmpassword: "",
notification: ""
}
};
}
если вы не используете import React, { Component } from 'react';, но вы не включили это в свой пост, поэтому я сделал React.Component.
Так почему же this работает неправильно внутри createNewUserWithEmailPassword()?
Чтобы понять это, нам нужно хорошее представление о том, как значение this определяется внутри функции.
class Car {
setDriveSound(){
this.sound = sound;
}
drive() {
return this.sound;
}
}
Это просто фиктивный класс, который позволяет нам установить значение, а затем вернуть это значение.
class Car {
setDriveSound(sound){
this.sound = sound;
}
drive() {
return this.sound;
}
}
const car = new Car();
car.setDriveSound('vroom');
car.drive();
Это выведет vroom.
Итак, вот важное правило, которое необходимо понять. Всякий раз, когда мы хотим выяснить, какое значение this будет внутри метода класса, не смотрите на сам метод, посмотрите на то, где вы его вызвали.
В моем примере выше мы смотрим на car.drive();.
Мы находим имя функции, в данном случае drive(), смотрим на точку слева от функции и смотрим на переменную, на которую есть ссылка внутри.
Таким образом, this из return this.sound; внутри метода drive() будет равен переменной car внутри класса Car.
Так что не смотрите на функцию, смотрите на то, где она вызывается. Что находится слева от точки при вызове функции.
Таким образом, когда drive() вызывается на car, this становится равным экземпляру car.
Я создам объект с именем truck, скопирую функцию drive() из экземпляра car и назначу ее объекту грузовика:
const truck = {
sound: "honk_honk",
driveMyTruck: car.drive
}
truck.driveMyTruck();
Это вернет honk_honk, потому что truck равен this внутри функции drive().
Последнее эквивалентно выполнению:
drive() {
return truck.sound;
}
Давайте применим вышеизложенное к тому, что происходит в вашем случае.
Теперь, если я попробую это:
const drive = car.drive;
drive();
Теперь получил бы Cannot read property 'sound' of undefined.
Поэтому, когда обратный вызов передается элементу формы в какой-то момент времени, мы собираемся вызвать createNewUserWithEmailPassword(), а когда он будет вызван, LogincreateNewUserWithEmailPassword не будет.
Вот этот пример:
class Car {
setDriveSound(sound){
this.sound = sound;
}
drive() {
return this.sound;
}
}
const car = new Car();
car.setDriveSound('vroom');
const drive = car.drive;
drive();
это именно то, что вы сделали или что у вас происходит.
Это все еще может сбивать с толку, это непростая концепция для понимания, я тоже очень часто получаю сообщения об ошибках такого типа.
Итак, как бы вы применили то, что я только что объяснил?
Есть несколько способов решить вашу проблему.
Теперь вы добавили метод constructor(props) с super(props), потому что он расширяет React.Component, и вы сделали this.createNewUserWithEmailPassword = this.createNewUserWithEmailPassword.bind(this);
Это должно было привести к созданию новой версии функции, и она должна была быть исправлена с правильным значением this, но это не решило проблему.
Так что попробуйте это:
class Login extends React.Component {
state = {
sign_up_details: {
email: "",
password: "",
confirmpassword: "",
notification: ""
}
};
createNewUserWithEmailPassword = (event) => {
event.preventDefault();
console.info(this.state.sign_up_details);
}
}
На какой линии вы столкнулись с этой проблемой? Убедитесь, что ваши функции, использующие
this, привязаны к классу.