Open creamidea opened 2 years ago
有如下代码,静态编写多子组件,不会出现 key 警告
export function App({ name }) { return ( <div> <h1>{name}</h1> <h1>{name}</h1> <h1>{name}</h1> </div> ) }
但是,如果使用动态的形式创建多个子组件,就会出现 key 警告
export function App({ name }) { return ( <div> { [1,2,3].map(id => { return <h2>{id}</h2> }) } </div> ) }
在新版 JSX 解析的过程中,开启如下配置
那么在分析 JSX 代码的时候,对于静态多个子组件,会对其父组件使用 jsxs。而对于动态版本,则会使用 jsx
jsxs
jsx
jsxs 和 jsx 函数定义在文件 packages/react-reconciler/src/ReactChildFiber.new.js
通过第四个参数控制,如果为 true,则会进入 validateChildKeys -> validateExplicitKey 提前设置 element._store.validated = true;。那么在 reconcileChildrenArray 阶段,warnForMissingKey 函数会在判断 !child._store || child._store.validated || child.key != null 提前返回(child._store.validated 为 true)
element._store.validated = true;
!child._store || child._store.validated || child.key != null
child._store.validated
validateExplicitKey (index.js:formatted:2473) validateChildKeys (index.js:formatted:2473) jsxWithValidation (index.js:formatted:2473) <- 这里调用时,第四个参数为 false App (App5.js:6) renderWithHooks (index.js:formatted:2473) mountIndeterminateComponent (index.js:formatted:2473) beginWork (index.js:formatted:2473) beginWork$1 (index.js:formatted:2473) performUnitOfWork (index.js:formatted:2473) workLoopSync (index.js:formatted:2473) renderRootSync (index.js:formatted:2473) performSyncWorkOnRoot (index.js:formatted:2473) scheduleUpdateOnFiber (index.js:formatted:2473) updateContainer (index.js:formatted:2473) (anonymous) (index.js:formatted:2473) unbatchedUpdates (index.js:formatted:2473) legacyRenderSubtreeIntoContainer (index.js:formatted:2473) render (index.js:formatted:2473) (anonymous) (index.js:10) ./src/index.js (index.js:24) __webpack_require__ (bootstrap:856) fn (bootstrap:150) 1 (reportWebVitals.js:14) __webpack_require__ (bootstrap:856) checkDeferredModules (bootstrap:45) webpackJsonpCallback (bootstrap:32) (anonymous) (main.chunk.js:1)
https://github.com/reactjs/rfcs/pull/107
问题描述
有如下代码,静态编写多子组件,不会出现 key 警告
但是,如果使用动态的形式创建多个子组件,就会出现 key 警告
原理探索
在新版 JSX 解析的过程中,开启如下配置
那么在分析 JSX 代码的时候,对于静态多个子组件,会对其父组件使用
jsxs
。而对于动态版本,则会使用jsx
jsxs
和jsx
函数定义在文件 packages/react-reconciler/src/ReactChildFiber.new.js通过第四个参数控制,如果为 true,则会进入 validateChildKeys -> validateExplicitKey 提前设置
element._store.validated = true;
。那么在 reconcileChildrenArray 阶段,warnForMissingKey 函数会在判断!child._store || child._store.validated || child.key != null
提前返回(child._store.validated
为 true)附 警告时调用堆栈