The reference app could be found here.
- Place the front-end code in a separate repo.
- Create a boilerplate with
create-react-app
. - Keep
.env
in the root of the front-end repo, not insrc/API/
. - Use boilerplate generator like one from https://github.com/react-boilerplate/react-boilerplate.
$ npm run generate container Foo
will create a bunch of files and directories that otherwise you would be creating manually (all with contents!):components/Foo/
components/Foo/index.js
components/Foo/Foo.js
components/Foo/Foo.test.js
components/Foo/Foo.css
containers/FooContainer/
containers/FooContainer/index.js
containers/FooContainer/FooContainer.js
- Define
main
property inpackage.json
.
Justification: see the NPM docs.
- Put each React component in a module with an interface specified in its
index.js
. - Make
components/
a module withindex.js
with an entry for each exported component:
export { default as Component } from './Component'
- Make
containers/
a module withindex.js
with the same entry for each exported component. - Eliminate
src/vendor/
. Keep vendor assets inpublic/vendor
(only if they are absolutely needed). - Refactor imports according to proposals above.
becomesimport BlogItem from '@src/Components/BlogItem/BlogItem' import Button from '@src/Components/Button/Button'
import { BlogItem, Button } from '@src/components'
- Extract container component from
containers/Foo/index.js
intocontainers/Foo/FooContainer.js
.
Justification:connect()
returns a container component. Each importable component should reside in a separate module. - Move presentational components from
containers/
tocomponents/
.
containers/BlogItems/BlogItems.jsx
->components/BlogItems/BlogItems.jsx
.
Justification:/* In containers/BlogItemsContainer/BlogItemsContainer.js */ import { BlogItems } from '@src/components' ...
components/
should contain all presentational components, not only shared ones. - Eliminate
Routes
module; move the components it contains tocomponents/
. Justification: the components it contains are just presentational components renderingSwitch
'es andRoute
's.
- Move
App
tocomponents
. Justification: it's just a presentational component. As all presentational components, it should reside incomponents/
. - Eliminate
Routes/Groups/
component; move routes up toApp
.
Justification: we use React Router v4. It follows and proclaims the dynamic routing philosophy. We should not try to emulate the static routing approach with it. Also, we should not be afraid of nested routes as they are means of declarative routing (remember the React Router slogan: "Declarative routing for React"). You can see an example of applying this approach in React Router 4: A Practical Introduction
- Introduce
Api
singleton composed with domain-specific mixins instead of the existing bunch of functions.
Justification: we should follow rules of object-oriented design. It will allow us to deduplicate the code, test and maintain it with ease. Example implementation TBD.
- Rename each module that does not export React component or constructor with camelCase.
Justification: in the React world, PascalCase is reserved for constructors and components. - Rename
.jsx
files to.js
. - Add
Container
postfix to container components' names.
Justification: this way, we will be able to distinguish between presentational and container components right in JSX, without need to scroll up to imports. This approach is recommended by Redux maintainers and is used in example app https://codesandbox.io/s/github/reactjs/redux/tree/master/examples/shopping-cart - Rename
BlogItems
toBlogItemList
.
Justification: in the React world,List
is the standard postfix for a list of items. - Rename
app.js
toindex.js
.
Justification: it's needed to definepackage.main
. - Rename
index_reset.css
toindex.css
.
- Reduce Redux-related boilerplate using helper libraries
flux-standard-action
,redux-actions
,redux-thunk-actions
. - Do not define action types separately -- only in
createAction()
. Do not dispatch bare actions -- call action creators.