React状态更新疑问及编译警告解决求助
React表单状态更新问题与编译警告解决
编译警告解决
你遇到的编译警告是由于react-bootstrap包的source map文件缺失导致的,有几种可行的解决方式:
- 重新安装react-bootstrap:删除
node_modules和package-lock.json,执行npm install重新安装依赖 - 禁用source-map-loader对node_modules的处理:在webpack配置中修改source-map-loader规则,排除node_modules目录
- 临时忽略警告:在项目根目录的
.env文件中添加GENERATE_SOURCEMAP=false,关闭source map生成
技术疑问解答
1. 初始化state时{user: new User()}与直接new User()的区别
{user: new User()}:state是包含user字段的普通对象,后续可以轻松扩展其他状态(比如loading、error等),符合React推荐的state使用方式(优先普通对象,便于不可变更新)- 直接
new User():state本身就是User类的实例,后续若要添加其他状态必须重构state结构;而且类实例的不可变性处理更麻烦,React的state更新依赖浅比较,类实例的引用变化检测不如普通对象直观,容易引发不必要的重渲染或更新不生效问题
2. state更新逻辑中...state、...state.user的作用及是否必要
...state:完全多余且错误,当前state结构是{user: User实例},展开state会把user字段直接放到新的user对象中,导致新user对象出现嵌套的user属性,破坏数据结构...state.user:必要且正确,作用是浅复制原User对象的所有属性,保证state更新的不可变性(React要求state更新必须返回新对象,不能直接修改原state),再通过[e.target.name]: e.target.value覆盖当前输入的字段值- 修正后的更新逻辑:
let updateInput = (e) =>{ setState({ user: { ...state.user, [e.target.name] : e.target.value } }) }
3. 输入框name属性与User对象属性匹配的合理性
这种做法是React表单处理的最佳实践之一,非常合理:
- 可复用同一个
updateInput处理函数,无需为每个输入框单独编写更新逻辑,减少代码冗余 - 字段扩展更便捷,后续新增User属性时,只需添加对应name的输入框即可,无需修改更新逻辑
- 逻辑清晰,输入框与数据模型的对应关系一目了然
附上代码
User类定义
export default class User { constructor(email = '', password = '') { this.email = email; this.password = password; } } module.exports = User;
Register组件代码
import React from 'react'; import {Col, Row, Container, Card, Button} from 'react-bootstrap' import Form from 'react-bootstrap/Form'; import { useState } from 'react'; import User from 'models/user.js' let Register = () => { let [state, setState] = useState({user: new User()}); let updateInput = (e) =>{ setState({ user: { ...state.user, [e.target.name] : e.target.value } }) } let register = (e) =>{ e.preventDefault(); // 阻止表单默认提交行为 console.log(`registerclick`, state.user) } return ( <> <Container className='mt-3'> <Row> <Col xs={3}> <Card className="shadow-lg"> <Card.Header className='p-3'> Register </Card.Header> <Card.Body> <Form onSubmit={register}> {/* 绑定表单提交事件 */} <Form.Group className="mb-3"> <Form.Control name="email" onChange={updateInput} type="text" placeholder="email"/> </Form.Group> <Form.Group className="mb-3"> <Form.Control name="password" onChange={updateInput} type="password" placeholder="password"/> </Form.Group> <Form.Group className="mb-3"> <Button type="submit">Register</Button> </Form.Group> </Form> </Card.Body> </Card> </Col> </Row> </Container> </> ) } export default Register;
编译警告信息
Compiled with warnings. Failed to parse source map from 'C:\Users\manuchadha\OneDrive - Microsoft\Manu_Personal\leren\views\reactfrontend\node_modules\react-bootstrap\dist\module.js.map' file: Error: ENOENT: no such file or directory, open 'C:\Users\manuchadha\OneDrive - Microsoft\Manu_Personal\leren\views\reactfrontend\node_modules\react-bootstrap\dist\module.js.map' Search for the keywords to learn more about each warning. To ignore, add // eslint-disable-next-line to the line before. WARNING in ./node_modules/react-bootstrap/dist/react-bootstrap.js Module Warning (from ./node_modules/source-map-loader/dist/cjs.js): Failed to parse source map from 'C:\Users\manuchadha\OneDrive - Microsoft\Manu_Personal\leren\views\reactfrontend\node_modules\react-bootstrap\dist\module.js.map' file: Error: ENOENT: no such file or directory, open 'C:\Users\manuchadha\OneDrive - Microsoft\Manu_Personal\leren\views\reactfrontend\node_modules\react-bootstrap\dist\module.js.map' webpack compiled with 1 warning
内容的提问来源于stack exchange,提问作者Manu Chadha
相关产品推荐
相关产品推荐

