react-ready-app v2.0.1
React Ready App
Based by create-react-app
Installation
npm install -g react-ready-app
Quick start
Write in your terminal next command create-react-ready-app
create-react-ready-app
In which directory to create the template?
MyProject
✔ Success
Next steps...
cd MyProject
npm install
Example project
What packages will you get?
- react
- redux
- redux-form
- react-router
- bootstrap-sass
- normalize-json-api
- lifecycle-connector
- react-helmet
- react-ladda
- react-feather
- ramda
- lodash
What ready things will you get?
- App structure
- React structure
- Redux store structure
- Environment varibales
- API connecting
- Routes
- Redux-form components
- User authentication flow
- Styles structure
App 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 |
React structure
You will get structure for work react components
└─ components
│ ├─ User
│ | ├─ SignInForm
│ │ │ ├─ Component.js
│ │ │ ├─ Container.js
│ │ │ └─ index.js
│ | └─ SignUpForm
│ │ ├─ Component.js
│ │ ├─ Container.js
│ │ └─ index.js
Usage
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 SignIn
Redux store structure
You 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
│ └─ ...
Reducers
You will get ready reducers for User
and Entities
.
Reducer Entities
adapted for any entities which you get from response in json-api format
Usage
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
Response
{
"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
}
}
]
}
Store
{
"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"]
}
}
}
Actions
Write actions for special entity.
Selectors
You will get ready selectors for work with entities.
Usage
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
Environment varibales
You will get opportunity to use environment variables
├─ .env
└─ .env.dev
Usage
In .env
NODE_PATH=src/
REACT_APP_MY_VARIABLE="SOME VARIABLE"
process.env.REACT_APP_MY_VARIABLE // return "SOME VARIABLE"
Api connecting
You will get ready HTTP methods for request to your API.
All response keys will be converted to comfortable CamelCase
format.
Usage
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 })
Routes
You will get ready routes, like that:
AuthRoute
Use for path where must be only authenticated user
In src/App.js
...
<AuthRoute path={Path.UPDATE_PASSWORD} component={Pages.UpdatePassword} />
...
UnAuthRoute
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 />
...
MetaRoute
Add to pages meta info by their path. Based by react-helmet. Configuration example of meta info by path.
Redux-form components
You will get ready components for which work with redux-form
Fields
Fields contain components for form fields, like that: input
, area
, 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 SomeForm
Form button
Form 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 SomeForm
User authentication flow
You will get ready standard user authentication flows, like that:
- Sign in
- Sign up
- OAuth
- Sign out
- Forgot password
- Reset password
- Update password
Styles structure
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';
License
The components is available as open source under the terms of the MIT License.