From 7325ebe4d6e5b7ccf5a78128b825c8a6e383caa6 Mon Sep 17 00:00:00 2001 From: Brian Vaughn <brian.david.vaughn@gmail.com> Date: Thu, 13 Dec 2018 09:40:59 -0800 Subject: [PATCH] Inject overrideProps() fn to DevTools (#14427) * Inject overrideProps() fn to DevTools This function will enable editing props for function components, host nodes, and special types like memo and forwardRef. --- .../src/ReactFiberReconciler.js | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/packages/react-reconciler/src/ReactFiberReconciler.js b/packages/react-reconciler/src/ReactFiberReconciler.js index 665e02938f164..b75057c527862 100644 --- a/packages/react-reconciler/src/ReactFiberReconciler.js +++ b/packages/react-reconciler/src/ReactFiberReconciler.js @@ -62,6 +62,7 @@ import { current as ReactCurrentFiberCurrent, } from './ReactCurrentFiber'; import {StrictMode} from './ReactTypeOfMode'; +import {Sync} from './ReactFiberExpirationTime'; type OpaqueRoot = FiberRoot; @@ -339,10 +340,49 @@ export function findHostInstanceWithNoPortals( return hostFiber.stateNode; } +let overrideProps = null; + +if (__DEV__) { + const copyWithSetImpl = ( + obj: Object | Array<any>, + path: Array<string | number>, + idx: number, + value: any, + ) => { + if (idx >= path.length) { + return value; + } + const key = path[idx]; + const updated = Array.isArray(obj) ? obj.slice() : {...obj}; + // $FlowFixMe number or string is fine here + updated[key] = copyWithSetImpl(obj[key], path, idx + 1, value); + return updated; + }; + + const copyWithSet = ( + obj: Object | Array<any>, + path: Array<string | number>, + value: any, + ): Object | Array<any> => { + return copyWithSetImpl(obj, path, 0, value); + }; + + // Support DevTools props for function components, forwardRef, memo, host components, etc. + overrideProps = (fiber: Fiber, path: Array<string | number>, value: any) => { + flushPassiveEffects(); + fiber.pendingProps = copyWithSet(fiber.memoizedProps, path, value); + if (fiber.alternate) { + fiber.alternate.pendingProps = fiber.pendingProps; + } + scheduleWork(fiber, Sync); + }; +} + export function injectIntoDevTools(devToolsConfig: DevToolsConfig): boolean { const {findFiberByHostInstance} = devToolsConfig; return injectInternals({ ...devToolsConfig, + overrideProps, findHostInstanceByFiber(fiber: Fiber): Instance | TextInstance | null { const hostFiber = findCurrentHostFiber(fiber); if (hostFiber === null) {