【发布时间】:2019-11-05 11:47:42
【问题描述】:
我正在尝试为注册表单设置错误消息,但因为我使用的是 Material UI,所以我不得不为我的项目使用功能组件。我正在关注 youtube 上的教程,但那个人正在使用类组件。我设法将大部分代码转换为功能组件,但我迷失在 componentDidUpdate 函数中。
我也尝试使用 useEffect 功能,但无济于事,当有人单击提交按钮时,如果他们没有输入任何字段,我无法显示警报/消息错误。我还收到一个错误,即 msg 未在 SignUp 组件的 Alert 组件中定义,尽管它已在 useState 函数中定义。
{msg ? <Alert color="danger">{msg}</Alert> : null}
下面是注册组件的代码
import React, { useState, useEffect } from "react";
import Avatar from "@material-ui/core/Avatar";
import Button from "@material-ui/core/Button";
import CssBaseline from "@material-ui/core/CssBaseline";
import TextField from "@material-ui/core/TextField";
import Link from "@material-ui/core/Link";
import Grid from "@material-ui/core/Grid";
import Box from "@material-ui/core/Box";
import Typography from "@material-ui/core/Typography";
import { makeStyles } from "@material-ui/core/styles";
import Container from "@material-ui/core/Container";
import Logo from "./assets/images/logo_transparent.png";
import { Alert } from "reactstrap";
//redux
import { connect } from "react-redux";
//proptypes
import PropTypes from "prop-types";
import { register } from "./actions/authActions";
const useStyles = makeStyles(theme => ({
//styles- for brevity only
}));
function SignUp(props) {
const classes = useStyles();
const [form, setValues] = useState({
name: "",
email: "",
password: "",
msg: null
});
// Similar to componentDidMount and componentDidUpdate
//By running an empty array [] as a second argument,
//we’re letting React know that the useEffect function doesn’t
//depend on any values from props or state.
useEffect(() => {
const { error } = props;
if (error !== form.error) {
//check for register error
if (error.id === "REGISTER_FAIL") {
setValues({ msg: error.msg.msg });
} else {
setValues({ msg: null });
}
}
}, []);
const onChange = e => {
setValues({
...form,
[e.target.name]: e.target.value,
[e.target.email]: e.target.value,
[e.target.password]: e.target.value
});
};
const handleClick = e => {
e.preventDefault();
const { name, email, password } = form;
//create user object
const newUser = {
name,
email,
password
};
//attempt to register
props.register(newUser);
window.confirm("Registration details: " + name + " " + email);
//window.location.href = "http://localhost:3000/";
};
return (
<Container component="main" maxWidth="xs">
<CssBaseline />
<div className={classes.paper}>
{msg ? <Alert color="danger">{msg}</Alert> : null}
<form className={classes.form} noValidate>
<Grid container spacing={2}>
<Grid item xs={12}>
<TextField
autoComplete="name"
name="name"
variant="outlined"
required
fullWidth
id="name"
label="Full Name"
autoFocus
onChange={onChange}
/>
</Grid>
<Grid item xs={12}>
<TextField
variant="outlined"
required
fullWidth
id="email"
label="Email Address"
name="email"
autoComplete="email"
onChange={onChange}
/>
</Grid>
<Grid item xs={12}>
<TextField
variant="outlined"
required
fullWidth
name="password"
label="Password"
type="password"
autoComplete="current-password"
onChange={onChange}
/>
</Grid>
<Grid item xs={12}>
<TextField
variant="outlined"
required
fullWidth
name="cpassword"
label="Confirm Password"
type="password"
id="cpassword"
autoComplete="confirm-password"
/>
</Grid>
<Grid item xs={12} />
</Grid>
<Button
type="submit"
fullWidth
variant="contained"
color="primary"
className={classes.submit}
onClick={handleClick}
>
Sign Up
</Button>
<Button
href="http://localhost:3000/"
fullWidth
variant="contained"
color="primary"
className={classes.home}
>
Home
</Button>
<br />
<br />
<Grid container justify="flex-end">
<Grid item>
<Link href="http://localhost:3000/signin" variant="body2">
Already have an account? Sign in
</Link>
</Grid>
</Grid>
</form>
</div>
<Box mt={5}>
</Box>
</Container>
);
}
SignUp.propTypes = {
isAuthenticated: PropTypes.bool,
error: PropTypes.object.isRequired,
register: PropTypes.func.isRequired
};
const mapStateToProps = state => ({
isAuthenticated: state.auth.isAuthenticated,
error: state.error //getting from reducer
});
export default connect(
mapStateToProps,
{ register } //from redux actions //mapdispatchtoprop
)(SignUp); //component
这是原来的componentDidUpdate函数
componentDidUpdate(prevProps) {
const {error} = this.props;
if(error !== prevProps.error){
//check for register error
if(error.id === "REGISTER_FAIL"){
this.setState({msg:error.msg.msg});
}else {
setValues({ msg: null });
}
}
}
【问题讨论】:
-
这绝对应该是一个基于类的组件,恕我直言,在这里使用功能组件没有意义。
-
嗨@TobiasTengler。请问为什么函数组件(FC)不能在这里工作?我想知道为什么(不想争论,只是想了解你的思维过程????)
-
我从来没有说过它不起作用,只是基于类的组件对我个人来说更有意义。一般来说,功能组件应该是 dumb 并且只渲染通过 props 提供给它们的东西。那里有一堆处理程序,OP 希望通过引入生命周期挂钩来增加更多复杂性。我猜 React 鼓励 FC 作为最近的更新,也许我只是在这方面过时,谁知道,只是个人喜好。
-
对不起,我看错了你之前的消息????...所以我的理解是,FC应该用作“演示文稿”,而CC(类组件)用作“容器/控制器”?
-
@TobiasTengler 我理解你的观点,即使用类组件要好得多,但我仍在尝试学习 Hooks 以使功能组件具有状态。另外,据我所知,material-ui 不支持类组件。
标签: javascript reactjs use-effect