我正在开发一个React JS Web应用程序。我是新来的反应js。现在,我试图在无状态功能组件中使用Ref来检索输入值。我遵循了在网上找到的一些解决方案。
这是我的组成部分
const Login = (props) => {
const {
classes,
width
} = props;
// Flip container to column on mobile screens.
const panelDirection = width === 'xs' ? 'column' : 'row';
let emailInput = null;
let passwordInput = null;
return (
<Grid
container
direction="row"
spacing={0}
justify="center"
alignItems="center"
className={classes.background}
>
<Grid item sm={10} xs={12} className={scss.panel}>
<form className="full-height" action="post">
<Grid direction={panelDirection} container spacing={0}>
<Grid
item
sm={6}
xs={12}
>
<Card className={classNames(scss.card, classes['primary-card'])}>
<CardContent className={scss['signup-content']}>
<img src={logoImage} className={scss['signup-logo']} alt="logo" />
<Typography variant="headline" component="h2" gutterBottom>
Web Portal
</Typography>
</CardContent>
<CardActions>
<Button fullWidth href="/register" color="secondary" variant="raised">Create an account</Button>
</CardActions>
</Card>
</Grid>
<Grid
item
sm={6}
xs={12}
>
<Card className={scss.card}>
<CardContent>
<TextField
ref={(input) => { emailInput = input }}
label="Email Address"
fullWidth
/>
<TextField
ref={(input) => { passwordInput = input }}
label="Password"
fullWidth
margin="normal"
type="password"
/>
</CardContent>
<CardActions className={scss['login-actions']}>
<Button href="/login" color="primary" variant="raised">Login</Button>
<Button href="/forgot-password">Forgot Password</Button>
</CardActions>
</Card>
</Grid>
</Grid>
</form>
</Grid>
</Grid>
);
};
如您所见,我正在使用ref来检索电子邮件和密码输入字段的值。但是,当我跑步时,它仍然给我这个错误。
Warning: Stateless function components cannot be given refs. Attempts to access this ref will fail.
那么,如何解决我的代码?如何在无状态功能组件中正确使用Ref?
很明显,我遵循了这个How can I attach to a stateless component's ref in React?
我也尝试使用该类。这给了我同样的错误。这是我组件的类版本。
class Login extends React.Component {
submitForm = e => {
e.preventDefault();
}
constructor(props)
{
super(props);
this.emailInput = React.createRef();
this.passwordInput = React.createRef();
}
render () {
const { classes, width } = this.props;
// Flip container to column on mobile screens.
const panelDirection = width === 'xs' ? 'column' : 'row';
return (
<Grid
container
direction="row"
spacing={0}
justify="center"
alignItems="center"
className={classes.background}
>
<Grid item sm={10} xs={12} className={scss.panel}>
<form className="full-height" action="post" onSubmit={this.submitForm}>
<Grid direction={panelDirection} container spacing={0}>
<Grid
item
sm={6}
xs={12}
>
<Card className={classNames(scss.card, classes['primary-card'])}>
<CardContent className={scss['signup-content']}>
<img src={logoImage} className={scss['signup-logo']} alt="logo" />
<Typography variant="headline" component="h2" gutterBottom>
Web Portal
</Typography>
</CardContent>
<CardActions>
<Button fullWidth href="/register" color="secondary" variant="raised">Create an account</Button>
</CardActions>
</Card>
</Grid>
<Grid
item
sm={6}
xs={12}
>
<Card className={scss.card}>
<CardContent>
<TextField
ref={this.emailInput}
label="Email Address"
fullWidth
/>
<TextField
ref={this.passwordInput}
label="Password"
fullWidth
margin="normal"
type="password"
/>
</CardContent>
<CardActions className={scss['login-actions']}>
<Button type="submit" color="primary" variant="raised">Login</Button>
<Button href="/forgot-password">Forgot Password</Button>
</CardActions>
</Card>
</Grid>
</Grid>
</form>
</Grid>
</Grid>
)
}
}
Login.propTypes = {
classes: PropTypes.shape({}).isRequired,
width: PropTypes.string.isRequired
};
export default compose(withWidth(), withStyles(themeStyles, { withTheme: true }))(Login);
答案 0 :(得分:1)
缺少状态的组件意味着它不包含状态,该组件仅通过道具进行更新。因此,您可以使用class
容器。这是解决方案...
import React, { Component } from "react";
class Login extends Component {
constructor(props) {
super(props);
this.emailInput = React.createRef();
this.passwordInput = React.createRef();
}
render() {
const { classes, width } = this.props;
// Flip container to column on mobile screens.
const panelDirection = width === "xs" ? "column" : "row";
return (
<Grid container direction="row" spacing={0} justify="center" alignItems="center" className={classes.background}>
<Grid item sm={10} xs={12} className={scss.panel}>
<form className="full-height" action="post">
<Grid direction={panelDirection} container spacing={0}>
<Grid item sm={6} xs={12}>
<Card className={classNames(scss.card, classes["primary-card"])}>
<CardContent className={scss["signup-content"]}>
<img src={logoImage} className={scss["signup-logo"]} alt="logo" />
<Typography variant="headline" component="h2" gutterBottom>
Web Portal
</Typography>
</CardContent>
<CardActions>
<Button fullWidth href="/register" color="secondary" variant="raised">
Create an account
</Button>
</CardActions>
</Card>
</Grid>
<Grid item sm={6} xs={12}>
<Card className={scss.card}>
<CardContent>
<TextField ref={this.emailInput} label="Email Address" fullWidth />
<TextField ref={this.passwordInput} label="Password" fullWidth margin="normal" type="password" />
</CardContent>
<CardActions className={scss["login-actions"]}>
<Button href="/login" color="primary" variant="raised">
Login
</Button>
<Button href="/forgot-password">Forgot Password</Button>
</CardActions>
</Card>
</Grid>
</Grid>
</form>
</Grid>
</Grid>
)
}
}
export default Login;
现在您可以像这样获得文本字段的值
this.emailInput.current.value
和this.passwordInput.current.value
答案 1 :(得分:0)
如果您坚持使用无状态组件(对我来说这很棒),则应该使用回调来检索输入值:
// Login.js
const Login = (props) => {
const {
classes,
width,
onChange, // <- get the callback here
} = props;
...
return (
...
<TextField
name="email"
onChange={onChange}
label="Email Address"
fullWidth
/>
<TextField
name="password"
onChange={onChange}
label="Password"
fullWidth
margin="normal"
type="password"
/>
...
);
// Somewhere to include Login
class LoginPage extends Component {
...
handleInputChange({ target }) {
...
console.log(target.name, target.value);
}
render (
<Login onChange={this.handleInputChange} ... />
)
}
// Or connect it to Redux
const mapDispatchToProps = dispatch => {
const updateLoginInputValues = ({ target }) => dispatch(updateLoginInputValues(target.name, target.value)));
return {
onChange: updateLoginInputValues,
}
};
const connectedLogin = connect(null, mapDispatchToProps)(Login
您唯一可以改进的部分基本上是通过状态管理来处理值,或者直接通过React来处理。除此之外,您还需要在某个时候解决状态问题,并且不能使所有组件保持无状态。