我正在研究一个Expressjs项目来服务React构建(使用npm run build
)。每当我为React项目提供服务时,它都会很棒。构建项目并与express.static('build')
一起使用时,出现错误。
我有一个联系表,当我按发送时,页面变为空白,并且在开发人员工具控制台中显示错误:
不变违规:“最小化React错误#31;访问https://reactjs.org/docs/error-decoder.html?invariant=31&args[]=object%20with%20keys%20%7Bname%2C%20data%2C%20stage%7D&args[]=获取完整消息,或使用非最小化dev环境获取完整错误和其他有用的警告。”
在该页面中,我得到了已解析的错误:
对象无效,不能作为React子对象(找到:带有键{name,data,stage}的对象)
我有组件Contacto.js
,其中:
import React, { Component } from "react";
import ReCAPTCHA from "react-google-recaptcha";
import "./Contacto.css";
const Validator = require("validator");
const queryString = require("query-string");
const errores = {
nombre: {
vacio: "El nombre es obligatorio"
},
apellido: {
vacio: "El apellido es obligatorio"
},
email: {
vacio: "El correo electrónico es obligatorio",
invalido: "El correo electrónico es inválido"
},
telefono: {
vacio: "El teléfono es obligatorio"
},
asunto: {
vacio: "El asunto es obligatorio"
},
mensaje: {
vacio: "El mensaje es obligatorio"
},
captcha: "El captcha es obligatorio"
};
class Contacto extends Component {
constructor(props) {
super(props);
this.state = {
error: false,
texto: {},
alert: {
tipo: ""
},
captcha: "",
captchaSiteKey: "<captcha key>",
captchaTestSiteKey: "<captcha test key>"
};
this.checkField = this.checkField.bind(this);
this.enviarCorreo = this.enviarCorreo.bind(this);
this.setCaptcha = this.setCaptcha.bind(this);
}
checkField(e) {
let errors = { ...this.state.texto };
if (Validator.isEmpty(e.target.value)) {
if (typeof errores[e.target.id].vacio != "undefined") {
errors[e.target.id] = <p>{errores[e.target.id].vacio}</p>;
} else {
errors[e.target.id] = <p>{errores[e.target.id]}</p>;
}
} else {
delete errors[e.target.id];
}
if (Object.keys(errors).length < 1) {
this.setState(
Object.assign(this.state, {
error: false
})
);
}
this.setState(Object.assign(this.state, { texto: errors }));
}
enviarCorreo(evt) {
evt.preventDefault();
const data = {
nombre: evt.target.elements.nombre.value,
apellido: evt.target.elements.apellido.value,
email: evt.target.elements.email.value,
telefono: evt.target.elements.telefono.value,
asunto: evt.target.elements.asunto.value,
mensaje: evt.target.elements.mensaje.value
};
let errors = {};
if (Validator.isEmpty(data.nombre)) {
this.setState(Object.assign(this.state, { error: true }));
errors.nombre = <p>{errores.nombre.vacio}</p>;
}
if (Validator.isEmpty(data.apellido)) {
this.setState(Object.assign(this.state, { error: true }));
errors.apellido = <p>{errores.apellido.vacio}</p>;
}
if (Validator.isEmpty(data.email)) {
this.setState(Object.assign(this.state, { error: true }));
errors.email = <p>{errores.email.vacio}</p>;
} else if (!Validator.isEmail(data.email)) {
this.setState(Object.assign(this.state, { error: true }));
errors.email = <p>{errores.email.invalido}</p>;
}
if (Validator.isEmpty(data.telefono)) {
this.setState(Object.assign(this.state, { error: true }));
errors.telefono = <p>{errores.telefono.vacio}</p>;
}
if (Validator.isEmpty(data.asunto)) {
this.setState(Object.assign(this.state, { error: true }));
errors.asunto = <p>{errores.asunto.vacio}</p>;
}
if (Validator.isEmpty(data.mensaje)) {
this.setState(Object.assign(this.state, { error: true }));
errors.mensaje = <p>{errores.mensaje.vacio}</p>;
}
if (!this.state.captcha.length) {
this.setState(Object.assign(this.state, { error: true }));
errors.captcha = <p>{errores.captcha}</p>;
}
if (this.state.error) {
this.setState(
Object.assign(this.state, {
texto: errors,
error: false,
alert: {
tipo: "alert-danger"
}
})
);
} else {
this.setState(
Object.assign(this.state, {
error: false
})
);
const options = {
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded"
},
body: queryString.stringify(data)
};
// If I remove the following block of code, the error is not being displayed.
(async () => {
let response = await fetch(
`${window.location.origin}/contacto`,
options
);
let data = await response.json();
if (!data.success) {
this.setState({
error: true,
texto: { error: <p>{data.message}</p> },
alert: {
tipo: "alert-danger"
}
});
} else {
this.setState({
error: false,
texto: { error: <p>{data.message}</p> },
alert: {
tipo: "alert-success"
}
});
document.getElementById("formulario-contacto").reset();
}
})();
}
}
setCaptcha(value) {
const mensajes = this.state.texto;
if (!!this.state.texto.captcha && value.length) {
delete mensajes.captcha;
} else {
mensajes.captcha = "El captcha es obligatorio";
}
this.setState(
Object.assign(this.state, {
captcha: value,
texto: mensajes
})
);
}
render() {
return (
<section id='contacto'>
<div
className={`alert ${this.state.alert.tipo}`}
style={{
display: !!Object.keys(this.state.texto).length ? "block" : "none"
}}
>
{Object.keys(this.state.texto).map(key => this.state.texto[key])}
</div>
<div className='container'>
<div className='row'>
<div className='col-xs-12 col-md-6'>
<div className='formulario-contacto'>
<form onSubmit={this.enviarCorreo} id='formulario-contacto'>
{/* Nombre */}
<div className='form-group'>
<div className='input-group'>
<span className='input-group-addon' />
<input
type='text'
className='form-control'
id='nombre'
aria-describedby='Nombre'
placeholder='Nombre'
onChange={this.checkField}
/>
</div>
{/* /form-group */}
</div>
{/* /Nombre */}
{/* Apellido */}
<div className='form-group'>
<div className='input-group'>
<span className='input-group-addon' />
<input
type='text'
className='form-control'
id='apellido'
aria-describedby='Apellido'
placeholder='Apellido'
onChange={this.checkField}
/>
</div>
{/* /form-group */}
</div>
{/* /Apellido */}
{/* Email */}
<div className='form-group'>
<div className='input-group'>
<span className='input-group-addon' />
<input
type='email'
className='form-control'
id='email'
aria-describedby='Email'
placeholder='Email'
onChange={this.checkField}
/>
</div>
{/* /form-group */}
</div>
{/* /Email */}
{/* Telefono */}
<div className='form-group'>
<div className='input-group'>
<span className='input-group-addon' />
<input
type='tel'
className='form-control'
id='telefono'
aria-describedby='Telefono'
placeholder='Telefono'
onChange={this.checkField}
/>
</div>
{/* /form-group */}
</div>
{/* /Telefono */}
{/* Asunto */}
<div className='form-group'>
<div className='input-group'>
<span className='input-group-addon' />
<input
type='text'
className='form-control'
id='asunto'
aria-describedby='Asunto'
placeholder='Asunto'
onChange={this.checkField}
/>
</div>
{/* /form-group */}
</div>
{/* /Asunto */}
{/* Mensaje */}
<div className='form-group'>
<div className='input-group'>
<span className='input-group-addon' />
<textarea
className='form-control'
id='mensaje'
rows='3'
placeholder='Escribe aqui tu consulta...'
onChange={this.checkField}
/>
</div>
{/* /form-group */}
</div>
{/* /Mensaje */}
<div className='col-xs-12 col-md-6'>
<ReCAPTCHA
sitekey={this.state.captchaSiteKey}
onChange={this.setCaptcha}
/>
</div>
{/* Boton Enviar */}
<div className='form-group'>
<button
type='submit'
className='btn btn-primary btn-lg btn-block'
>
Send
</button>
</div>
{/* /form-group */}
</form>
{/* /Formulario */}
</div>
{/* /Formulario Contacto */}
</div>
</div>
{/* /row */}
</div>
{/* /container */}
</section>
);
}
}
export default Contacto;
注意:这些错误会在警报div中很好地显示。
我正在阅读几个SO问题,但由于我的代码可与React Server一起使用,所以我不知道如何将其应用于代码。有什么想法吗?