Giter VIP home page Giter VIP logo

react-app-best-practice's Introduction

React Redux Sample

Description

React application bootstrapped with Create React App for using with REST API and Redux for state managing.

Both components and redux-specific code (reducers, actions, action types) splitted by feature-first pattern Re-Ducks.

File structure

src/
├── state/        => represents redux
├── views/        => all react components
└── utilities/    => global constants and helper functions

Redux

State folder contains usual store.js and folder ducks, where one 'duck' equals one feature with one reducer. One duck contains actions.js, redurers.js, types.js and optional utils.js.

ducks/
├── duck/
|   ├── actions.js
|   ├── reducers.js
|   ├── types.js
|   ├── utils.js
|   └── index.js
└── index.js

Since index.js of each duck have default export as this feature's reducer, index of ducks folder represents root reducer. So adding a new, changing or deleting existing features in redux being not so painful - all files, related to one feature concentrated in one folder.

It also prevents merge conflicts in situations, when several people working around different features need to touch same files, as types, actions, etc.

// ducks/index.js
export { reducer as form } from "redux-form"

export { default as user } from "./user"
export { default as profile } from "./profile"

/* ... */

// store.js
import * as reducers from "./ducks"

export default createStore(
  combineReducers(reducers),
  reduxDevTools,
  applyMiddleware(...middlewares you use)
)

Index of ducks/ folder = old root reducer with x2 less more code

One more thing about reducers

There is a helper function, called createReducer, used to create reducers, not using basic switch-case template.

const someReducer = createReducer(initialState)({
  [types.YOUR_ACTION_TYPE]: (state, action) => {
    const some_var = "";
    return {
      ...state,
      some_prop: action.payload
    };
  },

  [types.SOME_ANOTHER_TYPE]: (state, { payload: { data } }) => ({
    ...state,
    data,
    loading: false
  }),

  [types.MAY_BE_YOU_WANT_RESET]: (state, action) => ({
    ...initialState
  })
});

Its very useful, for example, if you need to scope out part of reducer to use variables with same name in several case statements.

Tip: switch-case template still can be useful when several types causes same reaction.

About actions

To handle asynchronous actions we usually using redux-thunk middleware and always using action creators.

const someAction = payload => ({
  type: types.SOME_YOUR_TYPE,
  payload
});

const someFetchAction = payload => (dispatch, getState) => {
  dispatch(setLoading(payload.id));

  fetch(GET, `/api_endpoint?some_parameter=${payload.id}`)
    .then(response => {
      if (getState().yourReducer.currentLoading === payload.id) {
        dispatch(setLoaded(response));
      }
    })
    .catch(error => {
      dispatch(setFail(error));
      console.error(error);
    });
};

React

views/
├── routes/       => base router
├── components/   => feature-first components
├── pages/        => layouts, related to routes
├── styled/       => StyledComponents
└── UI/           => reusable components

We splitting components to two parts - Container and Component.

Container file concentrates in itself all logic and HOCs of this feature.

Component itself usually a plain stateless component.

// FeatureContainer.js

import Feature from './Feature.jsx'

const withConnect = connect(...)

const withForm = reduxForm({
  ...
})

const enhance = compose(
  withConnect,
  withForm,
  anyOtherListedHOC
)

export default enhance(Feature)

// Feature.jsx

const Feature = ({props you needed}) => (
  /* some jsx code here */
)

export default Feature

License

react-app-best-practice is Copyright © 2015-2019 Codica. It is released under the MIT License.

About Codica

Codica logo

We love open source software! See our other projects or hire us to design, develop, and grow your product.

react-app-best-practice's People

Contributors

alexmalinin avatar dependabot[bot] avatar popinskisoda avatar rostislavkor avatar volkov-sergey avatar

Stargazers

 avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.