gohypergiant / react-component-hierarchy

A CLI app for visualizing how React components are structured in a project.
https://medium.com/bpxl-craft/introducing-react-component-hierarchy-35d5cc4d3782
MIT License
119 stars 25 forks source link

General Suggestions #5

Open fenos opened 8 years ago

fenos commented 8 years ago

Hi, this library is very very good, thanks!

I have few suggestions to improve it, cause i see very good potentials on automating scripts and understanding of the app Component Structure.


Public api

You should create a public api of the plugin instead of just command line. This will allow developer todo cool things with the Hierarchy object tree.

Example:

import rch from 'react-component-hierarchy';

const componentPath = path.resolve('mycomponentpath');
rch.tree(componentPath); // @returns components tree Object

Scenario: I'm working on internationalisation in my application, with react-intl. Their babel plugin allow me to extract automatically all the translations from the code into a json file. We have a lots translations going on, and file is very big,

I need a way to identify translations for each page within it children components. rch identify the Component structure just fine but only on command line which doesn't let me consume the object tree to extract the necessary translations from my top level component.


Don't Limit to only redux connected components

In my app i use few library which wrap the React component, ex: redux-form. The plugin is actually not displaying the children of my redux-form connected component.

Is there a way to let rch to let return the children on any wrapped component?


I'm open to contribute, just guide me on what you would like me to help with.

Thanks again for the great job.

Surreal9 commented 8 years ago

Interesting ideas. I don't think an API would be too hard to expose and could indeed be useful. It could build up the component tree and then the CLI tool could be responsible for showing it in the console.

As far as your second point, thanks for the heads up! It wasn't intentional to limit rch to redux connected components. If you have some example code to work with that would help. rch tries to scan through your source code's AST and find any children of the current component. It does that by either looking through any JSX or by seeing if an import is being used as an argument in a function being applied to the default export. It's possible there might be something avoiding that detection, and an example would help track it down. Thanks for your comments!

fenos commented 8 years ago

Thanks, for considering this, I worked on the problem number 1, to create a public api. You can see it here:

If you are happy with it i can make a PR.

Regarding the issue number 2, i'll provide you concrete examples sometime today/tomorrow. Thanks :)

redbar0n commented 6 years ago

@Surreal9

Project looks great and really simple to use!

One question though: Why the reliance on default exports? Is it possible/easy to work around this? (We don't use any default exports, since tooling is better with named exports.)

Surreal9 commented 6 years ago

@redbar0n thanks for the nice comment!

As far as the default export requirement, we just published version 1.1.0 which should allow named exports as well.

redbar0n commented 6 years ago

@Surreal9

First impressions are always helpful. So here's mine:

I tried it out on our project, and got this:

› rch app/src/App.js 
App
├── @expo/react-native-action-sheet/ActionSheetProvider
├── @modules/auth/AuthContext
├── @modules/auth/AuthProvider
├── @modules/onboarding/OnboardingProvider
├── @modules/profile/ProfileProvider
├── app/src/RootNavigator/RootNavigator
├─┬ app/src/RootQuery/RootQuery
│ ├── @modules/auth/LogOutLink
│ ├── @shared/DebugData
│ ├── @shared/ErrorMessage
│ ├── @shared/Loader
│ ├── react-apollo/Query
│ ├── react-native/Button
│ ├── react-native/ScrollView
│ └── react-native/View
├─┬ app/src/VehicleProvider/VehicleProvider
│ ├── @shared/Loader
│ ├── @shared/VehicleContext
│ └── react-apollo/Mutation
├── react-apollo/ApolloProvider
├── react-native/StatusBar
└── react-native/View

(I.e. a small slice of the top of our fairly large component hierarchy).

I'm a little confused on how the output is sorted. It seems to go through the render method from bottom-up, listing out the custom components it comes across. It then seems to list out components from other libraries (react-native, react-apollo etc.), in some predefined order? Maybe just continuing upwards in the file throughout the render method and then the imports?

What I expected initially was that it would do a top-down traversal of the render method.

Speaking of which: Since we're using react-navigation and a StackNavigator in our RootNavigator component, it seems we're out of luck, since RCH only seems to list what it can reach recursively through the render methods. It's be awesome if it would also interpret the StackNavigator definition, which is like:

export const RootNavigator = createStackNavigator(
  {
    Dashboard: {
      screen: Dashboard
    },
    CenterBooking: {
      screen: CenterBookingScreen
    },
    CenterProductInfo: {
      screen: CenterProductInfoScreen
    },
  },
  { 
    navigationOptions: { /* ... */ },
    transitionConfig: // ...
  }
);
Surreal9 commented 6 years ago

Ah interesting, so how rch works is by scanning a file for imports and then looking for a JSX tag that uses one of these imports. That import is then considered a 'child' of the scanned file and gets added to the list of next files to be parsed (as well as being added to the output). A recent PR added alphabetical sorting to the output (per depth). We've got some additional logic to attempt to account for HoC's that render their wrapped components by passing them to a function call; which is a bit kludgy.

While this works well for some architectures (ie how we were building apps 2 years ago when this tool was built), the drawback is it doesn't really understand which components are rendered as children of which other components, it basically just assumes a child is one file that is referred by another. I've seen the output for a more recent project, for example, which uses styled-components and it highlights some limitations of this approach as our styled components may be defined in another file but used in the first file, making what should be the child of the styled-component instead a child of the container.

Your case for react-navigation's createStackNavigator would require another custom bit of logic to look for that particular case, similar to what was done to account for react-router's Route component.

RebekahWolf commented 6 years ago

Hey John,

Will you or someone else at Black Pixel remove me from the bpxl-labs? I don’t work there anymore.

Thanks, Rebekah

From: John Arnold Sent: Wednesday, September 12, 2018 8:02 AM To: bpxl-labs/react-component-hierarchy Cc: Subscribed Subject: Re: [bpxl-labs/react-component-hierarchy] General Suggestions (#5)

Ah interesting, yeah so how rch works is by scanning a file for imports and then looking for a JSX tag that uses one of these imports. That import is then considered a 'child' of the scanned file and gets added to the list of next files to be parsed (as well as being added to the output). A recent PR added alphabetical sorting to the output (per depth). We've got some additional logic to attempt to account for HoC's that render their wrapped components by passing them to a function call; which is a bit kludgy. While this works well for some architectures (ie how we were building apps 2 years ago when this tool was built), the drawback is it doesn't really understand which components are rendered as children of which other components, it basically just assumes a child is one file that is referred by another. I've seen the output for a more recent project, for example, which uses styled-components and it highlights some limitations of this approach as our styled components may be defined in another file but used in the first file, making what should be the child of the styled-component instead a child of the container. Your case for react-navigation's createStackNavigator would require another custom bit of logic to look for that particular case, similar to what was done to account for react-router's Route component. — You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub, or mute the thread.

Surreal9 commented 6 years ago

Hey @RebekahWolf ! It looks like you have the repo on "watch", click the "Unwatch" button near the top bar to stop receiving notifications.