Организация компонентов в React проекте
- понедельник, 10 апреля 2017 г. в 03:15:04
Многие руководствуются рекомендациями Presentational and Container Components, но уважаемый автор признаётся в сносках, что концепция разделения спорная, и компоненты можно смешивать. А если это так, то зачем тащить чемодан без ручки? Все компоненты проекта удобнее хранить в одной общей папке. Какие плюсы:
- Простота навигации по файловой системе.
- Уникальные имена компонентов проекта.
- Импорт без боли ('../../../../../..').
Когда проект вырастет, следует дробить его на приватные npm-пакеты, инкапсулируя реализацию. Но не выращивать дерево подпапок внутри папки компонентов — развивать и поддерживать такое ощутимо сложнее. Проверено.
Все компоненты организованы по доменному принципу в одной папке src/componens. Например, можно определить домены: Post — отображение публикации, PostForm — форма редактирования публикации.
Как создать доменный компонент — src/components/Post/Post.js.
Почему нельзя использовать index.js вместо Post.js — соблюдается уникальность имен файлов компонентов внутри проекта, так упрощается навигация по вкладкам редактора (и в WebStorm будет работать ценная функция "Find Usages" для контекстного меню выделенного файла — см. примечание).
Все компоненты в папке доменного компонента получают префикс доменного компонента (Post*.js).
Подпапки в папке доменного компонента не допускаются, внутри плоская структура файлов из компонентов-потомков (PostTitle.js, PostBody.js) и компонентов-предков (PostViewPage.js, PostListPage.js). Компоненты-потомки используются внутри доменного компонента, а компоненты-предки используются снаружи (в роутере).
Чтобы инкапсулировать импорт доменных компонентов, следует задать внутри каждой папки доменного компонента свой package.json, в котором прописать точку входа "main":
{
"name": "Post",
"version": "0.0.0",
"private": true,
"main": "./Post.js",
}
Кроме того, внутри файла доменного компонента (Post.js) объявлен реэкспорт компонентов-предков:
import PostViewPage from './PostViewPage'
import PostListPage from './PostListPage'
//...
export { PostViewPage, PostListPage }
export default Post
К сожалению, нельзя использовать конструкцию "export from" (ограничение WebStorm), например:
export { default as PostViewPage } from './PostViewPage'
В результате не требуется явного доступа к файлам внутри папки компонентов, например:
import Post from 'components/Post/Post'
По соглашению, разрешается использовать импорт только по доменному имени компонента:
import Post, { PostViewPage, PostListPage } from 'components/Post'
Примечание по функции "Find Usages" в WebStorm. Как минимум, есть три контекста использования: 1) по выделенному файлу, 2) по выделенной переменной или символу, 3) по выделенному default в экспорте компонента.
1) Выделим файл components/Post/PostViewPage.js, результат поиска:
// Post.js
import PostViewPage from './PostViewPage'
2) Выделим символ PostViewPage внутри файла PostViewPage.js, результат поиска:
// PostViewPage.js
PostViewPage.propTypes = {}
3) Выделим default в экспорте компонента PostViewPage, результат поиска:
// routes.js
import { PostViewPage } from 'components/Post'
<Route exact path="/post/:id(\d+)/" component={PostViewPage} />
Как видно, третий способ использования выдает наиболее полезную информацию для компонента-предка.
PS
Найден правильный способ прикрутить Styled-JSX для Create React App. Теперь CSS-блоки живут внутри файлов компонентов естественным для себя образом — в CSS-формате (против инлайн-стилей JS-объектов). И не нужно беспокоиться за глобальную область видимости.
Работают относительно папки src, благодаря babel-plugin-module-resolver:
import MyComponent from 'components/MyComponent'
Для папки src в контекстом меню выполнить: Mark Directory as > Resource Root.
{
"moduleRoots": [
"../.."
}