React登录表单中no-shadow ESLint错误的解决咨询
解决React组件中ESLint的
no-shadow错误(login重名问题) 首先咱们理清问题根源:你遇到的no-shadow错误,是因为代码里存在两个同名的login标识符——一个是你从redux reducer文件导入的action creator函数,另一个是通过mapDispatchToProps注入到组件props里的同名函数。ESLint的no-shadow规则禁止在作用域内定义已经存在的变量,避免命名混淆,所以触发了这个错误。
另外要提醒你:你原来的onSubmit里直接调用login(username, password),其实是调用了未经过dispatch包装的原始action creator,这不会触发redux的状态更新,你的登录功能其实没真正生效哦!
下面给你几个优雅的解决方案,按简洁度排序:
方案一:使用React-Redux的对象简写(最推荐)
React-Redux的connect函数支持直接传入一个对象作为mapDispatchToProps,它会自动把对象里的每个action creator包装成带dispatch调用的函数,这样既避免了手动写mapDispatchToProps的冗余代码,又能解决命名冲突:
- 保留原有的导入语句:
import { login } from '../../redux/reducer';
- 修改
connect的第二个参数为对象:
// 替换原来的mapDispatchToProps定义 export default connect(mapStateToProps, { login })(LoginForm)
- 在
onSubmit里调用props里的login(已经被dispatch包装):
onSubmit = (e) => { e.preventDefault(); const { username, password } = this.state; this.props.login(username, password); }
这样修改后,导入的login和props里的login不会产生作用域冲突,ESLint的错误会消失,同时登录功能也能正确触发redux状态更新。
方案二:给导入的action creator起别名
如果不想用对象简写,你可以给导入的login起一个别名,比如loginAction,这样就不会和props里的login重名了:
- 修改导入语句:
import { login as loginAction } from '../../redux/reducer';
- 在
mapDispatchToProps里使用别名:
const mapDispatchToProps = (dispatch) => ({ login: (username, password) => dispatch(loginAction(username,password)) })
- 同样在
onSubmit里调用this.props.login(username, password)
方案三:重命名props里的函数
你也可以选择给注入到props里的函数换个名字,比如handleLogin,这样和导入的login区分开:
- 修改
mapDispatchToProps:
const mapDispatchToProps = (dispatch) => ({ handleLogin: (username, password) => dispatch(login(username,password)) })
- 更新组件的
propTypes和defaultProps:
LoginForm.propTypes = { isLoginPending: PropTypes.bool, isLoginSuccess: PropTypes.bool, loginError: PropTypes.string, handleLogin: PropTypes.func // 这里改成handleLogin }; LoginForm.defaultProps = { isLoginPending: false, isLoginSuccess: false, loginError: "", handleLogin: () => undefined // 对应修改 };
- 在
onSubmit里调用this.props.handleLogin(username, password)
修改后的完整代码(方案一)
import React, { Component } from 'react'; import PropTypes from 'prop-types'; import { connect } from 'react-redux'; import { Button, TextInput, Logo, Block } from 'vcc-ui'; import { login } from '../../redux/reducer'; import { styles } from './LoginForm-styles'; class LoginForm extends Component { constructor(props) { super(props); this.state = {}; } onSubmit = (e) => { e.preventDefault(); const { username, password } = this.state; // 调用props中已被dispatch包装的login函数 this.props.login(username, password); } render() { const {username, password} = this.state; const {isLoginPending, isLoginSuccess, loginError} = this.props; return ( <Block extend={styles.loginWrapper} > <Block extend={styles.loginForm} > <Block as="form" name="loginForm" onSubmit={this.onSubmit} > <Block extend={styles.loginLogo} > <Logo height="60"/> </Block> <Block extend={styles.loginInput} > <TextInput value={username} placeholder="username" type="text" name="username" onChange={e => this.setState({username: e.target.value})} /> </Block> <Block extend={styles.loginInput} > <TextInput value={password} placeholder="password" type="password" name="password" onChange={e => this.setState({password: e.target.value})} /> </Block> <Block extend={styles.loginButton} > <Button loading={isLoginPending} variant="outline" type="submit" fullWidth={["s","m","l"]} > Login </Button> </Block> {isLoginPending && <div>Processing</div>} {isLoginSuccess && <div>Logged In</div>} {loginError && <div>Incorrect Username or Password</div>} </Block> </Block> </Block> ) } } LoginForm.propTypes = { isLoginPending: PropTypes.bool, isLoginSuccess: PropTypes.bool, loginError: PropTypes.string, login: PropTypes.func }; LoginForm.defaultProps = { isLoginPending: false, isLoginSuccess: false, loginError: "", login: () => undefined }; const mapStateToProps = (state) => ({ isLoginPending: state.isLoginPending, isLoginSuccess: state.isLoginSuccess, loginError: state.loginError, }) // 使用对象简写形式的mapDispatchToProps export default connect(mapStateToProps, { login })(LoginForm)
内容的提问来源于stack exchange,提问作者Martin Fric
相关产品推荐
相关产品推荐

