- Installation and Running
- Concepts and Patterns
- What the App Does
- Recommended Learning Resources
- Soure Maps and Chrome Workspaces
- To Do
This project was bootstrapped with Create React App. See their page for information on how to perform common tasks including installation and running instructions. You can find the most recent version of their user guide here.
npm install
npm start
We support the standard Create React App scripts as well as the additional ones shown below.
Will use Prettier to reformat code to standard format used by this repo. Note that you will want to configure your editor to use prettier.
This is a boostrap that current demonstrates the concepts below. More details on these concepts coming soon.
- Recommended State Access Pattern - Selectors
- Recommended Folder Structure
- Recommened Async Pattern
- includes busy indicator
- includes support for stubbing sever responses (success and error) so that it's easy to build out features ahead of API code on the server
- Forms with Redux Forms
- Recommended auth (haven't done authz yet)
- includes restriced routes and redirect flow
- React Router 4
- React Router Redux Integration (The React Router folks recommend against this but we recommend this for better testing and debugging)
- Testing Approaches
We recommend only accessing state from selectors and not directly in components.
Good
const mapStateToProps = state => ({
userContext: getUserContext(state),
isAuthenticated: isAuthenticated(state)
});
Bad
const mapStateToProps = state => ({
userContext: state.userContext,
isAuthenticated: !_.isEmpty(state.userContext)
});
The benifits include:
- decoupling state structure from components
- this greatly improves your ability to refacotor you state atom shape and improve it over time by incorporating patterns like normalization.
- by also following Recommended Folder Structure we collocate the state shape with the module that owns that state and the associated reducers.
While deviating slightly, this recommenation also aligns well with both the redux documentation and the creator of Redux, Dan Abromov's, Idiomatic Redux course on EggHead. Note that using Reselect is an optomization and not essentail to the recommended approach.
We are following an approach here heavily inspired by Jack Hsu's recommended approach.
The basic idea is to treat each feature of the application like it's own node module with an index.js
file that defines it's public interface. Each module could implement the standard interface shown below.
// foo/index.js
import * as actions from './foo.actions';
import * as components from './components';
import * as constants from './foo.constants';
import reducer from './foo.reducer';
import * as selectors from './foo.selectors';
export default { actions, components, constants, reducer, selectors };
Some key difference to what Jack recommends are below.
- We are naming files
<featureName>.<componentType>.js
instead of<componentType>.js
. Examplefoo.actions.js
instead ofactions.js
. We are doing this because it makes searching the code base for files easier. - We are following Container\Presentational pattern and we are naming our container components
<FeatureName>Container.js
. ExampleFooContainer.js
. However, in ourfoo/components/index.js
file we are exporting the container components without theContainer
suffix as this is an internal implementation detail of the feature and we don't want all our markup to have<FooContainer/>
and<BarContainer/>
as most components will be containers and it will create noise in our DSL.
- src // all JS app code including tests, note node_modules is not under here
--modules // contains each feature module of the application, some have UI components and some don't
--screens // contains each of the screens in the app
We are following the recommendation that is straight out the redux documentation here where we create "tripples" of actions for each asynchrounous action creator as shown below.
{ type: 'FETCH_POSTS_REQUEST' }
{ type: 'FETCH_POSTS_FAILURE', error: 'Oops' }
{ type: 'FETCH_POSTS_SUCCESS', response: { ... } }
There is one exception. We are also following Flux Standard Actions pattern and so have payload instead of response as shown below.
{ type: 'FETCH_POSTS_SUCCESS', payload: { ... } }
This section is still being worked but below are some helpful links for setting up debugging of tests
- http://facebook.github.io/jest/docs/en/troubleshooting.html
- https://github.com/airbnb/enzyme
- http://facebook.github.io/jest/docs/en/troubleshooting.html
- It has a few routes that you can navigate two
- If you try and go to the "Protected" route and you haven't logged in you will be redirected to the Sign In page
- After signing in you will be redirected back to the "Protected" page
- If you enter an invalid password or an invalid user name, you will be shown an error panel. When navigating away from the sign in page the error pane will automatically be closed.
- When you make an asynchronous call to the server by signing in, there will be a busy indicator shown automatically while the data is being fetched.
If you are new to react or redux and want to get up to speed then we recommend these resources.
- Learn React and Flux basics: https://www.pluralsight.com/courses/react-flux-building-applications
- Learn Redux and ES6 basics: https://www.pluralsight.com/courses/react-redux-react-router-es6
- Learn Advanced Redux: https://egghead.io/courses/building-react-applications-with-idiomatic-redux
See this thread if you wan to get source maps working with chrome workspaces feature: webpack/webpack#6400
- Provide proptype warnings