EmailJS + React Hooks + 'preventDefault' 问题
Issue with EmailJS + React Hooks + 'preventDefault'
我已经使用 React 几个月了,我决定尝试构建我的作品集。为此,我默认使用 Material UI 表单,以便使用 EmailJS 平台进行联系。我确信这很简单,但是我已经花了好几个小时来解决这个问题而没有找到解决方案。
不知道是Material UI Librarie 的'Custom Input' 还是onClick 事件相关的问题。
我的问题是未定义的“e.preventDefault”。
这可能很简单,但是为了尝试解决它,我想我最终变得头晕目眩,并且比开始时更加困惑。
谢谢!
这是带有表单验证器的代码:
const [values, setValues] = useState({
name: '',
email: '',
message: '',
});
const handleChange = (name)=> (e) => {
setValues({ ...values, [e.target.id]: e.target.value });
};
const isFormValid = () => {
if (!values.name || !values.email || !values.message) {
return false;}
else {
return true;}
};
const sendEmail =(e) => {
e.preventDefault()
emailjs.sendForm('gmail', 'template_AILAIHUt', e.target, 'user_kPqhCaNpQHv75H92RjVhj')
.then((result) => {
console.log(result.text + 'funciona');
}, (error) => {
console.log(error.text + 'no funciona');
});
}
const handleSubmit = (e) => {
if (!isFormValid()) {
//message of error in the screen, maybe sweet alerts
console.log('falta algo')
}
else{ sendEmail(e)}
};
return (
<div className={classes.section}>
<div className={classes.container}>
<GridContainer justify="center">
<GridItem xs={12} sm={12} md={4}>
<Card>
<form className={classes.form}>
<CardHeader style={{ fontWeight: "fontWeightBold" }} color='primary' className={classes.cardHeader}>
<h4>Let's create something together </h4>
</CardHeader>
<CardBody>
<CustomInput
labelText="Name..."
id="name"
required={true}
formControlProps={{
required: true,
fullWidth: true
}}
inputProps={{
required: true,
onChange: handleChange(),
id:'name',
value: values.name,
type: "text",
endAdornment: (
<InputAdornment position="end">
<People className={classes.inputIconsColor} />
</InputAdornment>
)
}}
/>
<CustomInput
labelText="Email..."
id="email"
type='email'
required={true}
onChange={handleChange()}
formControlProps={{
required: true,
fullWidth: true
}}
inputProps={{
required: true,
onChange: handleChange(),
id:'email',
value: values.email,
type: "email",
endAdornment: (
<InputAdornment position="end">
<Email className={classes.inputIconsColor} />
</InputAdornment>
)
}}
/>
<CustomInput
labelText="Be free..."
id="message"
required={true}
formControlProps={{
size: 'large',
rows: '4',
required: true,
fullWidth: true
}}
inputProps={{
multiline: true,
required: true,
onChange: handleChange(),
id:'message',
value: values.message,
multiline: true,
type: "text",
endAdornment: (
<InputAdornment position="end">
<Icon className={classes.inputIconsColor}>
<SendIcon className={classes.inputIconsColor}/>
</Icon>
</InputAdornment>
),
autoComplete: "off"
}}
/>
</CardBody>
<CardFooter className={classes.cardFooter}>
<Button simple color="primary" size="lg" onClick={(e) => handleSubmit()}>
Submit
</Button>
</CardFooter>
</form>
</Card>
</GridItem>
</GridContainer>
</div>
</div>
);
}
请确保添加您收到的错误或您的代码在什么时候停止工作,以便我们更好地了解问题所在。
我已经在你的代码中看到了一些问题,我将在下面修复它们并在每个修复上方写一个大注释,这样你就可以确定我在哪里更改了代码。
const [values, setValues] = useState({
name: '',
email: '',
message: '',
});
const handleChange = (name)=> (e) => {
setValues({ ...values, [e.target.id]: e.target.value });
};
const isFormValid = () => {
if (!values.name || !values.email || !values.message) {
return false;}
else {
return true;}
};
const sendEmail = (e) => {
emailjs.sendForm('gmail', 'template_AILAIHUt', e.target, 'user_kPqhCaNpQHv75H92RjVhj')
.then((result) => {
console.log(result.text + 'funciona');
}, (error) => {
console.log(error.text + 'no funciona');
});
}
const handleSubmit = (e) => {
// HERE: you always want to prevent default, so do this first
e.preventDefault()
if (!isFormValid()) {
//message of error in the screen, maybe sweet alerts
console.log('falta algo')
} else{
sendEmail(e)
}
};
return (
<div className={classes.section}>
<div className={classes.container}>
<GridContainer justify="center">
<GridItem xs={12} sm={12} md={4}>
<Card>
<!-- HERE: use the FORM submit function and make sure to pass the event down to handleSubmit(e)@ -->
<form className={classes.form} onSubmit={(e) => handleSubmit(e)}>
<CardHeader style={{ fontWeight: "fontWeightBold" }} color='primary' className={classes.cardHeader}>
<h4>Let's create something together </h4>
</CardHeader>
<CardBody>
<CustomInput
labelText="Name..."
id="name"
required={true}
formControlProps={{
required: true,
fullWidth: true
}}
inputProps={{
required: true,
onChange: handleChange(),
id:'name',
value: values.name,
type: "text",
endAdornment: (
<InputAdornment position="end">
<People className={classes.inputIconsColor} />
</InputAdornment>
)
}}
/>
<CustomInput
labelText="Email..."
id="email"
type='email'
required={true}
onChange={handleChange()}
formControlProps={{
required: true,
fullWidth: true
}}
inputProps={{
required: true,
onChange: handleChange(),
id:'email',
value: values.email,
type: "email",
endAdornment: (
<InputAdornment position="end">
<Email className={classes.inputIconsColor} />
</InputAdornment>
)
}}
/>
<CustomInput
labelText="Be free..."
id="message"
required={true}
formControlProps={{
size: 'large',
rows: '4',
required: true,
fullWidth: true
}}
inputProps={{
multiline: true,
required: true,
onChange: handleChange(),
id:'message',
value: values.message,
multiline: true,
type: "text",
endAdornment: (
<InputAdornment position="end">
<Icon className={classes.inputIconsColor}>
<SendIcon className={classes.inputIconsColor}/>
</Icon>
</InputAdornment>
),
autoComplete: "off"
}}
/>
</CardBody>
<CardFooter className={classes.cardFooter}>
<input type="submit" value="Submit" />
</CardFooter>
</form>
</Card>
</GridItem>
</GridContainer>
</div>
</div>
);
}
到目前为止最大的收获,您有点混淆了表单逻辑。表单依赖于输入类型的提交按钮。此外,将 onSubmit 函数与提交输入元素一起使用。
如果您想使用表单并阻止提交时的默认事件,您必须使用输入类型提交按钮和表单的 onSubmit
功能。由于这是一个 React 应用程序,并且您根本不依赖表单事件,因此您也可以采用不同的方式(并保留您的样式按钮)。请参阅 this guide 了解如何使用自定义按钮提交表单。
有同样的问题,通过将 id 添加到表单并将其传递给 emailJS 方法解决了这个问题。
将 form-id 添加到 emailjs 方法:
emailjs
.sendForm(
"service_<id>",
"template_<id>",
"#contact-form",
"user_<id>"
)
然后到表单标签:
id="contact-form"
我已经使用 React 几个月了,我决定尝试构建我的作品集。为此,我默认使用 Material UI 表单,以便使用 EmailJS 平台进行联系。我确信这很简单,但是我已经花了好几个小时来解决这个问题而没有找到解决方案。 不知道是Material UI Librarie 的'Custom Input' 还是onClick 事件相关的问题。 我的问题是未定义的“e.preventDefault”。 这可能很简单,但是为了尝试解决它,我想我最终变得头晕目眩,并且比开始时更加困惑。 谢谢!
这是带有表单验证器的代码:
const [values, setValues] = useState({
name: '',
email: '',
message: '',
});
const handleChange = (name)=> (e) => {
setValues({ ...values, [e.target.id]: e.target.value });
};
const isFormValid = () => {
if (!values.name || !values.email || !values.message) {
return false;}
else {
return true;}
};
const sendEmail =(e) => {
e.preventDefault()
emailjs.sendForm('gmail', 'template_AILAIHUt', e.target, 'user_kPqhCaNpQHv75H92RjVhj')
.then((result) => {
console.log(result.text + 'funciona');
}, (error) => {
console.log(error.text + 'no funciona');
});
}
const handleSubmit = (e) => {
if (!isFormValid()) {
//message of error in the screen, maybe sweet alerts
console.log('falta algo')
}
else{ sendEmail(e)}
};
return (
<div className={classes.section}>
<div className={classes.container}>
<GridContainer justify="center">
<GridItem xs={12} sm={12} md={4}>
<Card>
<form className={classes.form}>
<CardHeader style={{ fontWeight: "fontWeightBold" }} color='primary' className={classes.cardHeader}>
<h4>Let's create something together </h4>
</CardHeader>
<CardBody>
<CustomInput
labelText="Name..."
id="name"
required={true}
formControlProps={{
required: true,
fullWidth: true
}}
inputProps={{
required: true,
onChange: handleChange(),
id:'name',
value: values.name,
type: "text",
endAdornment: (
<InputAdornment position="end">
<People className={classes.inputIconsColor} />
</InputAdornment>
)
}}
/>
<CustomInput
labelText="Email..."
id="email"
type='email'
required={true}
onChange={handleChange()}
formControlProps={{
required: true,
fullWidth: true
}}
inputProps={{
required: true,
onChange: handleChange(),
id:'email',
value: values.email,
type: "email",
endAdornment: (
<InputAdornment position="end">
<Email className={classes.inputIconsColor} />
</InputAdornment>
)
}}
/>
<CustomInput
labelText="Be free..."
id="message"
required={true}
formControlProps={{
size: 'large',
rows: '4',
required: true,
fullWidth: true
}}
inputProps={{
multiline: true,
required: true,
onChange: handleChange(),
id:'message',
value: values.message,
multiline: true,
type: "text",
endAdornment: (
<InputAdornment position="end">
<Icon className={classes.inputIconsColor}>
<SendIcon className={classes.inputIconsColor}/>
</Icon>
</InputAdornment>
),
autoComplete: "off"
}}
/>
</CardBody>
<CardFooter className={classes.cardFooter}>
<Button simple color="primary" size="lg" onClick={(e) => handleSubmit()}>
Submit
</Button>
</CardFooter>
</form>
</Card>
</GridItem>
</GridContainer>
</div>
</div>
);
}
请确保添加您收到的错误或您的代码在什么时候停止工作,以便我们更好地了解问题所在。
我已经在你的代码中看到了一些问题,我将在下面修复它们并在每个修复上方写一个大注释,这样你就可以确定我在哪里更改了代码。
const [values, setValues] = useState({
name: '',
email: '',
message: '',
});
const handleChange = (name)=> (e) => {
setValues({ ...values, [e.target.id]: e.target.value });
};
const isFormValid = () => {
if (!values.name || !values.email || !values.message) {
return false;}
else {
return true;}
};
const sendEmail = (e) => {
emailjs.sendForm('gmail', 'template_AILAIHUt', e.target, 'user_kPqhCaNpQHv75H92RjVhj')
.then((result) => {
console.log(result.text + 'funciona');
}, (error) => {
console.log(error.text + 'no funciona');
});
}
const handleSubmit = (e) => {
// HERE: you always want to prevent default, so do this first
e.preventDefault()
if (!isFormValid()) {
//message of error in the screen, maybe sweet alerts
console.log('falta algo')
} else{
sendEmail(e)
}
};
return (
<div className={classes.section}>
<div className={classes.container}>
<GridContainer justify="center">
<GridItem xs={12} sm={12} md={4}>
<Card>
<!-- HERE: use the FORM submit function and make sure to pass the event down to handleSubmit(e)@ -->
<form className={classes.form} onSubmit={(e) => handleSubmit(e)}>
<CardHeader style={{ fontWeight: "fontWeightBold" }} color='primary' className={classes.cardHeader}>
<h4>Let's create something together </h4>
</CardHeader>
<CardBody>
<CustomInput
labelText="Name..."
id="name"
required={true}
formControlProps={{
required: true,
fullWidth: true
}}
inputProps={{
required: true,
onChange: handleChange(),
id:'name',
value: values.name,
type: "text",
endAdornment: (
<InputAdornment position="end">
<People className={classes.inputIconsColor} />
</InputAdornment>
)
}}
/>
<CustomInput
labelText="Email..."
id="email"
type='email'
required={true}
onChange={handleChange()}
formControlProps={{
required: true,
fullWidth: true
}}
inputProps={{
required: true,
onChange: handleChange(),
id:'email',
value: values.email,
type: "email",
endAdornment: (
<InputAdornment position="end">
<Email className={classes.inputIconsColor} />
</InputAdornment>
)
}}
/>
<CustomInput
labelText="Be free..."
id="message"
required={true}
formControlProps={{
size: 'large',
rows: '4',
required: true,
fullWidth: true
}}
inputProps={{
multiline: true,
required: true,
onChange: handleChange(),
id:'message',
value: values.message,
multiline: true,
type: "text",
endAdornment: (
<InputAdornment position="end">
<Icon className={classes.inputIconsColor}>
<SendIcon className={classes.inputIconsColor}/>
</Icon>
</InputAdornment>
),
autoComplete: "off"
}}
/>
</CardBody>
<CardFooter className={classes.cardFooter}>
<input type="submit" value="Submit" />
</CardFooter>
</form>
</Card>
</GridItem>
</GridContainer>
</div>
</div>
);
}
到目前为止最大的收获,您有点混淆了表单逻辑。表单依赖于输入类型的提交按钮。此外,将 onSubmit 函数与提交输入元素一起使用。
如果您想使用表单并阻止提交时的默认事件,您必须使用输入类型提交按钮和表单的 onSubmit
功能。由于这是一个 React 应用程序,并且您根本不依赖表单事件,因此您也可以采用不同的方式(并保留您的样式按钮)。请参阅 this guide 了解如何使用自定义按钮提交表单。
有同样的问题,通过将 id 添加到表单并将其传递给 emailJS 方法解决了这个问题。
将 form-id 添加到 emailjs 方法:
emailjs
.sendForm(
"service_<id>",
"template_<id>",
"#contact-form",
"user_<id>"
)
然后到表单标签:
id="contact-form"