Skip to content
This repository was archived by the owner on Jun 26, 2020. It is now read-only.

[React Native] Add box inspect to NativeStyler#590

Merged
gaearon merged 13 commits into
facebook:masterfrom
jhen0409:box-inspect
Apr 25, 2017
Merged

[React Native] Add box inspect to NativeStyler#590
gaearon merged 13 commits into
facebook:masterfrom
jhen0409:box-inspect

Conversation

@jhen0409

@jhen0409 jhen0409 commented Mar 20, 2017

Copy link
Copy Markdown
Contributor

In React Native, it have the built-in inspector can show the component width / height / margin / padding information:

The built-in inspector contents will hidden when we use react-devtools, this PR made the box inspector showing in React Native Style Editor:

2017-03-20 5 06 59

@jaredly

jaredly commented Mar 31, 2017

Copy link
Copy Markdown
Contributor

coool I've definitely wanted this

top: number,
width: number,
height: number,
margin: Object,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like these margin and padding objects always need to contain { top: number, left: number, right: number, bottom: number } (since they are given to Box). If you typed them as such within Props, it'd make it clearer what kind of props you need to pass to a BoxInspector.

Also, If you want, you could extract a type with a name like BoxMeasurements or something, and share it between both Props and BoxProps.


class BoxInspector extends React.Component {
props: Props;
defaultProps: DefaultProps;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is telling flow that an instance of BoxInspector can have a property called defaultProps on it (the instance) of type DefaultProps. This seems incorrect; you normally only have a defaultProps property on the class, not the instance. In addition, I'm not sure what value typing defaultProps as DefaultProps adds, since DefaultProps is {}. Am I missing something here?

this.props.bridge.call('rn-style:get', this.props.id, style => {
this.setState({style});
});
(this:any)._styleGet = this._styleGet.bind(this);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do you have to annotate this as any here?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just avoid Property not found error of Flow, but I should define _styleGet: () => void; instead.

}
this.props.bridge.send('rn-style:set', {id: this.props.id, attr, val});
this.setState({style: this.state.style});
this.setState(this.state.style);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't look right. You're copying properties that are on the style object into the state itself.

It appears that this was happening before to force a re-render because the style object was mutated. This will still force a re-render, but adding a bunch of unrelated properties to the state is likely not what you are trying to do.

};

var Box = (props: BoxProps) => {
var box = props.box;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's kinda weird to have a Box that takes a prop called box. It seems like there is a name for a domain concept here that wants to be found. Maybe creating a type for { top: number, left: number, right: number, bottom: number } will help us find a clearer name to use for this prop.

Alternatively, perhaps top, left, right, and bottom could be made top-level props on the element itself:

<Box top={4} left={5} right={6} bottom={7} />

style[newName] = val;
this.props.bridge.send('rn-style:rename', {id: this.props.id, oldName, newName, val});
this.setState({style});
this.setState(this.state.style);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The above comment applies to this line as well (same situation).

@gaearon

gaearon commented Apr 20, 2017

Copy link
Copy Markdown
Contributor

Do you think there is any harm in just inlining resolveBoxStyle implementation? It doesn’t seem to have anything RN-specific per se (correct me if I’m wrong!) I’d like to avoid expanding API surface if we can just get by with some duplication.

@jhen0409

Copy link
Copy Markdown
Contributor Author

Ahh, yeah it haven't anything RN-specific, mirror it will be more cleaner and support current RN version.

I pushed new commits.

var bridge = new Bridge(wall);
var agent = new Agent(window, {
rnStyle: !!resolveRNStyle,
rnStyleMeasure: !!resolveRNStyle,

@gaearon gaearon Apr 20, 2017

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't need this anymore, do we? Seems like it would always be supported if rnStyle is enabled.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added measureSupport prop in NativeStyler (from store.capabilities.rnStyleMeasure) to backward compatibility for the backend vendor.

@gaearon gaearon Apr 20, 2017

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you explain why you can’t call measureStyle directly in the frontend where you display it instead of going through the bridge? (I’m not sure I understand this part of React DevTools so bear with me.) It would be cool if it “just worked” with old RN versions too. You could also remove the 'rn-style:measure' calls then.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The instance.measure is from RN UIManager.measure, it's native method.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, this makes sense. You can’t call it because it lives in the RN process.

bridge.send('rn-style:measure', {
id, style,
measureLayout: {
x, y,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please format each property on next line (above too).

@gaearon gaearon left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I’d like to better understand why the measurement code can’t completely move to frontend (and thus work on older RN versions).

@gaearon gaearon left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some naming change requests.

// TODO: typecheck bridge interface
bridge: any;
id: any;
measureSupport: boolean;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's call this supportsMeasure.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@gaearon done. :)


type State = {
style: ?Object;
measureLayout: ?Object;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's call this measuredLayout


type StyleResult = {
style: Object;
measureLayout: ?Object;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's call this measuredLayout

var padding = (style && resolveBoxStyle('padding', style)) || blank;
bridge.send('rn-style:measure', {
style,
measureLayout: {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

measuredLayout

@gaearon gaearon left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When editing styles, changes don’t seem to take effect immediately. I have to switch to another component and back to see the measurements change. Can we fix this?

gif

@jhen0409

Copy link
Copy Markdown
Contributor Author

It seems like have an async change in rename and set, so measureStyle will get old layout (apart from margin an padding), just set setTimeout for measureStyle it works fine.

@gaearon

gaearon commented Apr 25, 2017

Copy link
Copy Markdown
Contributor

Seems to work well. Thank you!

@gaearon gaearon merged commit dc8f87d into facebook:master Apr 25, 2017
@jhen0409 jhen0409 deleted the box-inspect branch May 23, 2017 18:41
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants