React Props为只读 为何两种场景修改props报错表现不一致
问题描述
以下是测试用的单页代码:
function Headline(props) { props.text = "I have changed."; return ( <h1>{props.text}</h1> ); } let title = <Headline text="Do Not Change" />; let app = document.getElementById("app"); ReactDOM.createRoot(app).render(title);
React官方文档明确说明Props为只读属性,但运行上述单页代码时,可以成功修改props的值,页面最终输出为"I have changed.",全程没有抛出任何错误,和文档描述的规则存在差异。
按照以下步骤用create-react-app搭建项目复现相同逻辑时,却触发了props修改的报错:
- 执行命令
npx create-react-app anything初始化React项目。
项目安装完成后,在src目录下创建两个文件:index.js 文件内容:
import React from 'react'; import ReactDOM from 'react-dom/client'; import Headline from './Headline'; import './index.css'; let title = <Headline text="Do Not Change" />; let app = document.getElementById("root"); ReactDOM.createRoot(app).render(title);
Headline.js 文件内容:
function Headline(props) { props.text = "I have changed."; return ( <h1>{props.text}</h1> ); } export default Headline;
运行该CRA项目后,控制台会抛出props修改相关错误,错误截图如下:
为什么同样的修改props逻辑,单页运行时无报错,在create-react-app搭建的项目中却会抛出props可变错误?
原因说明
两种运行场景表现不一致,核心是React不同构建版本的校验逻辑不一样:
- 单页直接引入的React运行时,默认是面向线上环境的生产构建版本。React仅在开发规范层面要求props只读,生产版本不会主动冻结props对象,也不会拦截对props的修改操作,所以修改props不会立刻抛出错误。但这种写法本身违反React单向数据流设计,后续组件触发重渲染时很容易出现数据不同步、渲染结果不符合预期的问题。
- create-react-app生成的项目,开发环境默认开启严格模式,同时加载带完整开发校验的React构建版本:这个版本会主动冻结传入组件的props对象,任何尝试修改props的操作都会立刻在控制台抛出错误,目的是在开发阶段就提前拦截不符合规范的写法,避免问题流到线上。
注意:哪怕单页场景下修改props没有报错,也永远不要直接修改props的值。如果需要基于传入的props值做调整,应该将对应值拷贝到组件本地state中再操作,避免破坏React的数据流逻辑。
内容的提问来源于stack exchange,提问作者Real Noob
相关产品推荐
相关产品推荐

