Skip to content

bezrukavyi/react-ready-app

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

13 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

React Ready App

Based by create-react-app

Quick start

git clone https://github.com/bezrukavyi/react-ready-app.git

cd react-ready-app

npm install

What packages will you get?

What ready things will you get?

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

Example

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, 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 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.