英文:
How to deal with a huge number of components in a page in React
问题
我发现在使用React几年后,一个良好的React组件通常有200-300行代码。不应该超过这个数量,否则阅读会变得困难。
这就是为什么在开发复杂页面时,我通常会尝试将它们分解为小组件,然后可以进一步分解为更小的组件,依此类推。
然而,这会引入一个新问题,那就是组件太多,而且大多数都不可重用。但它们提供了良好的可读性。
我看到了两种克服这个问题的方法:
一种方法是创建嵌套文件夹 components
。文件结构如下所示。
src/
├─ components/
│ ├─ Parent1/
│ │ ├─ index.tsx
│ │ ├─ components/
│ │ │ ├─ Child1/
│ │ │ │ ├─ index.tsx
│ │ │ │ ├─ components/
│ │ │ │ │ ├─ GrandChild1/
│ │ │ │ │ │ ├─ index.tsx
│ │ │ │ │ ├─ GrandChild2/
│ │ │ │ │ │ ├─ index.tsx
│ │ │ ├─ Child2/
│ │ │ │ ├─ index.tsx
│ ├─ Parent2/
│ │ ├─ index.tsx
这看起来确实很混乱,但我发现有一些优点:
- 层次结构使了解组件的构造变得更容易
- 组件应该只在其父文件夹内重复使用
另一种方法是扁平化上面的层次结构。将所有组件放入 /components
,不再嵌套 /components
文件夹。
您希望我提供哪种方法的建议吗?非常感谢!您也可以参考外部资源来获取更多意见。
英文:
After a few years working with React, I found out that 200-300 lines is a decent good React component. Shouldn't excess this number, otherwise, it'll be hard to read.
That's why when developing a complicated page, I usually try to break them into small components, which then can be broken into smaller components and so on.
However, this introduces a new issue that there are way too much components and most of them are not reusable at all. But they provide good readability.
I've seen 2 approaches to overcome this:
One would be creating nested folder components
. The file structure would look like this.
src/
├─ components/
│ ├─ Parent1/
│ │ ├─ index.tsx
│ │ ├─ components/
│ │ │ ├─ Child1/
│ │ │ │ ├─ index.tsx
│ │ │ │ ├─ components/
│ │ │ │ │ ├─ GrandChild1/
│ │ │ │ │ │ ├─ index.tsx
│ │ │ │ │ ├─ GrandChild2/
│ │ │ │ │ │ ├─ index.tsx
│ │ │ ├─ Child2/
│ │ │ │ ├─ index.tsx
│ ├─ Parent2/
│ │ ├─ index.tsx
It certainly looks horrible, but here are some advantages I found:
- Hierarchy makes it easier to know how a component is made of
- A component should be reused inside its parent folder only
Another would be flatten the hierarchy above. Put all components into /components
, no nest /components
folder
Can you give me some advice which approach to go? Thank you very much.
Even external resources are also highly appreciated!
答案1
得分: 1
以下是翻译好的部分:
"通过按用途或可重用性将组件分离,可以更清晰地保留层次结构行为。一个示例是在这个next-typescript starter中使用的,在实际项目中可能看起来像这样:
src/
├─ components/
│ ├─ common/
│ │ ├─ ReusableComponent.tsx
│ │ ├─ Carousel.tsx
│ ├─ layout/
│ │ ├─ header/
│ │ │ ├─ index.tsx
│ │ │ ├─ styles.css
│ │ ├─ footer/
│ │ │ ├─ index.tsx
│ │ │ ├─ styles.css
│ ├─ primitives/
│ │ ├─ Button.tsx
│ │ ├─ Link.tsx
│ ├─ sections/
│ │ ├─ home/
│ │ │ ├─ HeroComponent/
│ │ │ │ ├─ index.tsx
│ │ │ ├─ FeaturesComponent.tsx
英文:
You can keep the hierarchy behavior in a cleaner way by separating components by their use case or reusability.
An example of this is what is used in this next-typescript starter, that in a real project could look something like this:
<!-- begin snippet: js hide: false console: true babel: null -->
<!-- language: lang-js -->
src/
├─ components/
│ ├─ common/
│ │ ├─ ReusableComponent.tsx
│ │ ├─ Carousel.tsx
│ ├─ layout/
│ │ ├─ header/
│ │ │ ├─ index.tsx
│ │ │ ├─ styles.css
│ │ ├─ footer/
│ │ │ ├─ index.tsx
│ │ │ ├─ styles.css
│ ├─ primitives/
│ │ ├─ Button.tsx
│ │ ├─ Link.tsx
│ ├─ sections/
│ │ ├─ home/
│ │ │ ├─ HeroComponent/
│ │ │ │ ├─ index.tsx
│ │ │ ├─ FeaturesComponent.tsx
<!-- end snippet -->
答案2
得分: 0
我也喜欢小型组件(最多100-300行代码)。正如你所说,这可以使测试和可读性变得更容易。我认为最终这非常取决于开发团队的共识。
就我个人而言,我不太喜欢重复使用index.tsx
文件名。
以下是我喜欢使用的一种约定,已经在多个文件夹深度中使用,并包含大量小型组件。
src/
├─ components/
│ ├─ Parent1_/
│ │ ├─ ChildComponent_/
│ │ │ ├─ NestedComponent_/
│ │ │ │ ├─ NestedNestedComponent_/
│ │ │ │ ├─ NestedNestedComponent.tsx
│ │ │ ├─ NestedComponent.tsx
│ │ ├─ ChildComponent.tsx
│ ├─ Parent2_/
│ │ ├─ ChildComponent_/
│ │ │ ├─ NestedComponent_/
│ │ │ │ ├─ NestedNestedComponent_/
│ │ │ │ ├─ NestedNestedComponent.tsx
│ │ │ ├─ NestedComponent.tsx
│ │ ├─ ChildComponent.tsx
│ ├─ Parent1.tsx
│ ├─ Parent2.tsx
希望这对你有帮助。
英文:
I like small components as well (100-300 line range max). It makes testing and readability much easier as you said. I think it's very much up to the development team consensus in the end.
I'm personally not a huge fan of reusing the index.tsx
file name.
Here's a convention I enjoy using which has worked for me several folders deep with a large count of small components.
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
src/
├─ components/
│ ├─ Parent1_/
│ │ ├─ ChildComponent_/
│ │ │ ├─ NestedComponent_/
│ │ │ │ ├─ NestedNestedComponent_/
│ │ │ │ ├─ NestedNestedComponent.tsx
│ │ │ ├─ NestedComponent.tsx
│ │ ├─ ChildComponent.tsx
│ ├─ Parent2_/
│ │ ├─ ChildComponent_/
│ │ │ ├─ NestedComponent_/
│ │ │ │ ├─ NestedNestedComponent_/
│ │ │ │ ├─ NestedNestedComponent.tsx
│ │ │ ├─ NestedComponent.tsx
│ │ ├─ ChildComponent.tsx
│ ├─ Parent1.tsx
│ ├─ Parent2.tsx
<!-- end snippet -->
答案3
得分: 0
好的,以下是翻译好的部分:
然而,除此之外,将组件分组更具功能性是更好的。不要将所有组件放在components
文件夹中,可以创建名为layouts
、features
和pages
的新文件夹。这种方法被称为“Colocation”。
src/
├─ components/
│ ├─ form/
│ ├─ ui/
│ │ ├─ buttons/
│ │ ├─ cards/
│ │ ├─ modals/
│ ├─ index.tsx
│ |
├─ layouts/
│ ├─ navbar/
│ │ ├─ NavItem.tsx
│ │ ├─ NavItemDropdown.tsx
│ ├─ sidebar/
│ ├─ footer/
│ ├─ containers/
│ │ ├─ AuthLayout.tsx
│ │ ├─ MainLayout.tsx
│ ├─ index.tsx
│ |
├─ features/
│ ├─ authentication/
│ │ ├─ components/
│ │ │ ├─ LoginForm.tsx
│ │ ├─ hooks/
│ │ ├─ services/
│ ├─ todos/
│ │ ├─ components/
│ │ │ ├─ TodoList.tsx
│ │ │ ├─ TodoItem.tsx
│ │ │ ├─ form/
│ │ │ │ ├─ CreateTodoForm.tsx
│ │ │ │ ├─ EditTodoForm.tsx
│ │ ├─ contexts/
│ │ ├─ services/
│ ├─ index.tsx
│ |
├─ pages/
│ ├─ Login.tsx
│ ├─ Home.tsx
│ ├─ Todos.tsx
│ ├─ index.tsx
到目前为止,我可以看到一些好处:
- 所有内容都被安排在各自的位置,所以每当你想阅读关于“todos”的代码时,你确切地知道这些代码在哪里,你不需要在几个文件夹中查找它们。
- 文件夹
components
现在只包含通用组件,可以在项目的任何地方重复使用。对于不会在其他地方重复使用的特定组件,就让它们保持在它们的功能中。 - 你可以管理导出你需要的内容。
英文:
Well, personally, I prefer the 2nd approach that not to nest too many levels of components in each other.
But for the 1st way, you can improve it by replace the name of folder from components to your child component name. It still keeps your hierarchy and also can simplify 1 folder level for each one.
src/
├─ components/
│ ├─ Parent1/
│ │ ├─ index.tsx
│ │ ├─ Child1/
│ │ │ ├─ index.tsx
│ │ │ ├─ GrandChild1/
│ │ │ │ ├─ index.tsx
│ │ │ ├─ GrandChild2/
│ │ │ │ ├─ index.tsx
│ │ ├─ Child2/
│ │ │ ├─ index.tsx
│ ├─ Parent2/
│ │ ├─ index.tsx
However, beside that, it would be better to group components in a more functionable way. Instead of putting all components in the components
folder, you can create new folders named layouts
, features
& pages
. This approach is called "Colocation".
src/
├─ components/
│ ├─ form/
│ ├─ ui/
│ │ ├─ buttons/
│ │ ├─ cards/
│ │ ├─ modals/
│ ├─ index.tsx
│ |
├─ layouts/
│ ├─ navbar/
│ │ ├─ NavItem.tsx
│ │ ├─ NavItemDropdown.tsx
│ ├─ sidebar/
│ ├─ footer/
│ ├─ containers/
│ │ ├─ AuthLayout.tsx
│ │ ├─ MainLayout.tsx
│ ├─ index.tsx
│ |
├─ features/
│ ├─ authentication/
│ │ ├─ components/
│ │ │ ├─ LoginForm.tsx
│ │ ├─ hooks/
│ │ ├─ services/
│ ├─ todos/
│ │ ├─ components/
│ │ │ ├─ TodoList.tsx
│ │ │ ├─ TodoItem.tsx
│ │ │ ├─ form/
│ │ │ │ ├─ CreateTodoForm.tsx
│ │ │ │ ├─ EditTodoForm.tsx
│ │ ├─ contexts/
│ │ ├─ services/
│ ├─ index.tsx
│ |
├─ pages/
│ ├─ Login.tsx
│ ├─ Home.tsx
│ ├─ Todos.tsx
│ ├─ index.tsx
Here are some benefits that I can see so far:
- Everything are arrange in their own place so whenever you want to read code around "todos", you know exactly where those code are, you don't need to find them in several folders.
- Folder components now just includes the common components which can be reused anywhere in the project. For specific components that won't be reused somewhere else, just let them be in their feature.
- You can manage to export what you need.
References:
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论