Based by create-react-app
git clone https://github.com/bezrukavyi/react-ready-app.git
cd react-ready-app
npm install- react
- redux
- redux-form
- react-router
- bootstrap-sass
- normalize-json-api
- lifecycle-connector
- react-helmet
- react-ladda
- react-feather
- ramda
- lodash
- App structure
- React structure
- Redux store structure
- Environment varibales
- API connecting
- Routes
- Redux-form components
- User authentication flow
- Styles structure
You will get ready directories structure, which looks like:
├─ public
├─ src
│ ├─ components
│ ├─ constants
│ ├─ routes
│ ├─ store
│ ├─ styles
│ ├─ utils
│ ├─ App.js
│ ├─ index.js
│ ├─ registerServiceWorker.js
│ └─ storage.js
├─ .env
└─ .env.dev
| Directory | Contain |
|---|---|
components |
Components and containers |
constants |
Constants which you use in your project |
routes |
Custom routes |
store |
Logic which related with redux store (reducers, selectors, actions, types) |
styles |
SCSS files |
utils |
Your project helpers utils |
You will get structure for work react components
└─ components
│ ├─ User
│ | ├─ SignInForm
│ │ │ ├─ Component.js
│ │ │ ├─ Container.js
│ │ │ └─ index.js
│ | └─ SignUpForm
│ │ ├─ Component.js
│ │ ├─ Container.js
│ │ └─ index.js
In components/SignInForm/index.js
export { default } from './Container'In components/User/index.js
import { default as SignInForm } from './SignInForm'
import { default as SignUpForm } from './SignUpForm'
export default { SignInForm, SignUpForm }In components/Pages/SignIn.js
import React from 'react'
import User from 'components/User'
const SignIn = ({ children }) =>
<div>
<User.SignInForm />
</div>
export default SignInYou will get structure for work with redux store logic
└─ store
│ ├─ Api
│ ├─ Entities
│ | │ ├─ Project
│ │ │ │ ├─ actions.js
│ │ │ │ ├─ index.js
│ │ │ │ ├─ selectors.js
│ │ | │ └─ types.js
│ | │ └─ Task
│ │ │ ├─ actions.js
│ │ │ ├─ index.js
│ │ │ ├─ selectors.js
│ │ | └─ types.js
│ │ |
│ │ ├─ index.js
│ │ ├─ reducer.js
│ │ ├─ selectors.js
│ | └─ utils.js
│ ├─ User
│ └─ ...
You will get ready reducers for User and Entities.
Reducer Entities adapted for any entities which you get from response in json-api format
In src/store/Entities/reducer.js
import * as Utils from './utils'
import * as Project from './Project/types'
import { SUCCESS } from '../Api/types'
const entities = (state = {}, { type, payload }) => {
switch (type) {
case Project.PROJECT_LIST + SUCCESS: {
return Utils.complement(state, payload.data)
}
default:
return state
}
}
export default entities{
"data":[
{
"id":"1",
"type":"projects",
"attributes":{
"title":"Project 1",
},
"relationships":{
"tasks":{
"data":[
{
"id":"1",
"type":"tasks"
}
]
}
}
},
{
"id":"2",
"type":"projects",
"attributes":{
"title":"Project 2",
},
"relationships":{
"tasks":{
"data":[
{
"id":"2",
"type":"tasks"
}
]
}
}
}
],
"included":[
{
"id":"1",
"type":"tasks",
"attributes":{
"title":"Task 1.1",
"project-id":1
}
},
{
"id":"2",
"type":"tasks",
"attributes":{
"title":"Task 2.1",
"project-id":2
}
}
]
}{
"entities":{
"projects":{
"byId":{
"1":{ "id":"1", "type":"projects", "title":"Project 1", "tasks":["1"] },
"2":{ "id":"2", "type":"projects", "title":"Project 2", "tasks":["2"] }
},
"allIds":["1", "2"]
},
"tasks":{
"byId":{
"1":{ "id":"1", "type":"tasks", "title":"Task 1.1", "projectId":1 },
"2":{ "id":"2", "type":"tasks", "title":"Task 2.1", "projectId":2 }
},
"allIds":["1", "2"]
}
}
}Write actions for special entity.
You will get ready selectors for work with entities.
In src/store/Entities/selectors.js
import { values, map } from 'lodash'
import { store } from 'store'
const getEntities = () => store.getState().entities
export const allIds = (type) => values(get(getEntities(), `${type}.allIds`))
...In container.js
import Entities from 'store/Entities'
Entities.selectors.allIds('tasks')
// {
// "1":{ "id":"1", "type":"tasks", "title":"Task 1.1", "projectId":1 },
// "2":{ "id":"2", "type":"tasks", "title":"Task 2.1", "projectId":2 }
// }Also you can write you custom selectors for special entity
You will get opportunity to use environment variables
├─ .env
└─ .env.dev
In .env
NODE_PATH=src/
REACT_APP_MY_VARIABLE="SOME VARIABLE"
process.env.REACT_APP_MY_VARIABLE // return "SOME VARIABLE"You will get ready HTTP methods for request to your API.
All response keys will be converted to comfortable CamelCase format.
Set API url in .env
REACT_APP_API_DOMAIN="http://localhost:3000/api/v1/"
import Api from '../Api/actions'
import * as Types from './types'
export const postAction = (data) => Api.post('path', Types.ACTION_NAME, { data })You will get ready routes, like that:
Use for path where must be only authenticated user
In src/App.js
...
<AuthRoute path={Path.UPDATE_PASSWORD} component={Pages.UpdatePassword} />
...Use for path where authenticated user mustn't be
In src/App.js
...
<UnAuthRoute path={Path.ROOT} component={Pages.SignIn} exact />
<UnAuthRoute path={Path.SIGN_UP} component={Pages.SignUp} exact />
...Add to pages meta info by their path. Based by react-helmet. Configuration example of meta info by path.
You will get ready components for which work with redux-form
Fields contain components for form fields, like that: input, textarea, select, file
import React from 'react'
import { Fields } from 'components'
const SomeForm = ({ handleSubmit, error, submitting }) =>
<form onSubmit={handleSubmit}>
<Fields.Input name='title' type='text' placeholder='input' />
<Fields.FileInput name='file' type='file' placeholder='file' />
<Fields.Textarea name='textarea' type='text' placeholder='textarea' />
<Fields.Select name='select' type='text' placeholder='select' options={{
'option_name_1': 'option_value_1',
'option_name_2': 'option_value_2',
}}/>
...
</form>
export default SomeFormForm button based by react-ladda and adapted to redux-form
import React from 'react'
import { Buttons } from 'components'
const SomeForm = ({ handleSubmit, error, submitting }) =>
<form onSubmit={handleSubmit}>
...
<Buttons.Form className='black__theme' type='submit' loading={submitting} text='Submit' />
</form>
export default SomeFormYou will get ready standard user authentication flows, like that:
- Sign in
- Sign up
- OAuth
- Sign out
- Forgot password
- Reset password
- Update password
You will get ready structure for write styles rules
...
└─ styles
├─ components
│ ├─ Form.scss
│ ├─ Landing.scss
│ ├─ Input.scss
│ └─ ...
└─ App.scss
In App.scss include all your styles
...
/* Components */
@import 'components/Form.scss';
@import 'components/Landing.scss';
@import 'components/Input.scss';The components is available as open source under the terms of the MIT License.