diff --git a/backend/getData.js b/backend/getData.js index 49d031bda8..ea0ff00893 100644 --- a/backend/getData.js +++ b/backend/getData.js @@ -112,6 +112,15 @@ function getData(element: Object): DataType { } } + if (typeof element.setNativeProps === 'function') { + // For editing styles in RN + updater = { + setNativeProps(nativeProps) { + element.setNativeProps(nativeProps); + }, + }; + } + return { nodeType, type, diff --git a/backend/getDataFiber.js b/backend/getDataFiber.js index 8233487fde..d669b7a3ac 100644 --- a/backend/getDataFiber.js +++ b/backend/getDataFiber.js @@ -80,7 +80,11 @@ function getDataFiber(fiber: Object, getOpaqueNode: (fiber: Object) => Object): break; case HostComponent: nodeType = 'Native'; - name = fiber.type; + name = typeof fiber.type === 'string' ? + fiber.type : + // Necessary for React Native Fiber if host types are not strings. + // https://github.com/facebook/react/pull/9013 + getDisplayName(fiber.type); props = fiber.memoizedProps; if ( typeof props.children === 'string' || @@ -90,6 +94,14 @@ function getDataFiber(fiber: Object, getOpaqueNode: (fiber: Object) => Object): } else { children = []; } + if (typeof fiber.stateNode.setNativeProps === 'function') { + // For editing styles in RN + updater = { + setNativeProps(nativeProps) { + fiber.stateNode.setNativeProps(nativeProps); + }, + }; + } break; case HostText: nodeType = 'Text'; @@ -133,7 +145,14 @@ function getDataFiber(fiber: Object, getOpaqueNode: (fiber: Object) => Object): } function setInProps(fiber, path: Array, value: any) { - fiber.pendingProps = copyWithSet(fiber.memoizedProps, path, value); + const inst = fiber.stateNode; + fiber.pendingProps = copyWithSet(inst.props, path, value); + if (fiber.alternate) { + // We don't know which fiber is the current one because DevTools may bail out of getDataFiber() call, + // and so the data object may refer to another version of the fiber. Therefore we update pendingProps + // on both. I hope that this is safe. + fiber.alternate.pendingProps = fiber.pendingProps; + } fiber.stateNode.forceUpdate(); } diff --git a/backend/types.js b/backend/types.js index 35cc16bc60..3b1a7726f5 100644 --- a/backend/types.js +++ b/backend/types.js @@ -10,6 +10,17 @@ */ 'use strict'; +type CompositeUpdater = { + setInProps: ?(path: Array, value: any) => void, + setInState: ?(path: Array, value: any) => void, + setInContext: ?(path: Array, value: any) => void, + forceUpdate: ?() => void, +}; + +type NativeUpdater = { + setNativeProps: ?(nativeProps: {[key: string]: any}) => void, +}; + export type DataType = { nodeType: 'Native' | 'Wrapper' | 'NativeWrapper' | 'Composite' | 'Text' | 'Portal' | 'Empty', type: ?(string | AnyFn), @@ -22,13 +33,7 @@ export type DataType = { context: ?Object, children: ?(string | Array), text: ?string, - updater: ?{ - setInProps: ?(path: Array, value: any) => void, - setInState: ?(path: Array, value: any) => void, - setInContext: ?(path: Array, value: any) => void, - // setState: ?(newState: any) => void, - forceUpdate: ?() => void, - }, + updater: ?(CompositeUpdater | NativeUpdater), publicInstance: ?Object, }; diff --git a/plugins/ReactNativeStyle/setupBackend.js b/plugins/ReactNativeStyle/setupBackend.js index 0c2d085280..39982b75ec 100644 --- a/plugins/ReactNativeStyle/setupBackend.js +++ b/plugins/ReactNativeStyle/setupBackend.js @@ -43,11 +43,20 @@ function renameStyle(agent, id, oldName, newName, val) { var data = agent.elementData.get(id); var newStyle = {[newName]: val}; if (!data || !data.updater || !data.updater.setInProps) { - var el = agent.reactElements.get(id); - if (el && el.setNativeProps) { - el.setNativeProps({ style: newStyle }); + if (data && data.updater && data.updater.setNativeProps) { + data.updater.setNativeProps({ style: newStyle }); } else { - console.error('Unable to set style for this element... (no forceUpdate or setNativeProps)'); + // + // We can remove this when we stop supporting RN versions + // before https://github.com/facebook/react-devtools/pull/528. + // Newer versions use `updater.setNativeProps` instead. + var el = agent.reactElements.get(id); + if (el && el.setNativeProps) { + el.setNativeProps({ style: newStyle }); + } else { + console.error('Unable to set style for this element... (no forceUpdate or setNativeProps)'); + } + // } return; } @@ -84,11 +93,20 @@ function setStyle(agent, id, attr, val) { var data = agent.elementData.get(id); var newStyle = {[attr]: val}; if (!data || !data.updater || !data.updater.setInProps) { - var el = agent.reactElements.get(id); - if (el && el.setNativeProps) { - el.setNativeProps({ style: newStyle }); + if (data && data.updater && data.updater.setNativeProps) { + data.updater.setNativeProps({ style: newStyle }); } else { - console.error('Unable to set style for this element... (no forceUpdate or setNativeProps)'); + // + // We can remove this when we stop supporting RN versions + // before https://github.com/facebook/react-devtools/pull/528. + // Newer versions use `updater.setNativeProps` instead. + var el = agent.reactElements.get(id); + if (el && el.setNativeProps) { + el.setNativeProps({ style: newStyle }); + } else { + console.error('Unable to set style for this element... (no forceUpdate or setNativeProps)'); + } + // } return; }