react-devstack
An ultimate opinionated universal React devstack. Don't hassle with project build and other stuff, just do what matters: start developing your application, right now!
Getting started
In order to get started as easily as possible, we have prepared CLI utility to make app bootstrapping a breeze.
- Install
react-devstack-cli
globally using:npm install react-devstack-cli -g
- Create an empty React project using the CLI (it's called
rdc
):rdc create project-name
- After generating the project, CLI will guide you, however in case you wondered just:
cd project-name
- And start the app using
npm run dev
It will automatically open your browser upon compilation.
Enjoy all the hot-reloading, server side rendering etc. :-)
redux)
State management (usingreact-devstack
is packed with Redux for dealing with state. Redux provides single store instance which holds all the state information in one place. Start using redux
is as simple as creating root reducer in src/reducers/rootReducer.js
.
state = 0 type
And then just simply connect
any component you need. For instance, you can connect
the Root
. State corresponding with the rootReducer.js
is actually nested under key root
in global application state passed to connect. Therefore you can either access the field directly using root
key, or use getRootState
selector from react-devstack
.
;;; ; const mapStateToProps = clicked: stateroot // Or simply use Selectors.getRootState(state); const mapDispatchToProps = type: 'Increment' mapStateToProps mapDispatchToProps <div> <h1>Hello from react-devstack!</h1> <img src=logo width=200 /> <button onClick=increment>Button clicked clicked times</button> </div>;
react-devstack-cli
offers easy way to create root reducer for you. Just use rdc add redux
in your project.
router5)
Routing (usingFundamental part of every real application is routing. react-devstack
utilizes router5
as underlying routing library and it's automatically synchronized with redux
. Adding routing to your project involves creating routing schema file as defined by router5
. Just create a file named src/routing/routes.js
and export list of routes:
name: 'index' path: '/' name: 'cats' path: '/cats';
Now, whenever in your code, you can just use Selectors.getRoute
which returns active route object. The object contains field name
so that you can conditionally check in any component.
; const Root = isRouteFound activeRoute <div> isRouteFound && <div> activeRoutename === 'cats' && <Cats /> activeRoutename === 'index' && <Index /> </div> !isRouteFound && <div>404</div> </div>; const mapStateToProps = isRouteFound: !Selectors activeRoute: Selectors; mapStateToPropsRoot;
react-devstack-cli
offers easy way to create routing file for you. Just use rdc add routing
in your project.
Links
react-devstack
exposes Link
component. You need to provide route name as the only required property. Child of the component should be a function returning markup. This function is called with three important arguments: onClick
, href
, active
and props
originally passed to the component, so that you can define your own markup.
; const Root = <div> <Link name="cats"> active ? <span>Cats</span> : <a href=href onClick=onClick>Cats</a></Link> </div>; ;
However, it's better to create re-usable component which could look as follows:
;; // It's better to have this function stored so that// it's not being re-created with each render// unlike anonymous functionconst render = active ? <span>propsoriginalChildren</span> : <a href=href onClick=onClick>propsoriginalChildren</a>; const MyApplicationLink = <Link ...props originalChildren=propschildren>render</Link>;
Now it can be used like a simple component:
const Root = <div> <MyApplicationLink name="cats">Cats</MyApplicationLink> </div>; ;
It's highly recommended to read through router5 documentation.
redux-saga)
Data fetching (usingGenerally react-devstack
utilizes redux-saga
to deal with side effects. You don't need to install nor setup anything. Everything is already plugged in and it's up to you to just create src/sagas/rootSaga.js
and export generator function which will act as your root saga.
You can also use react-devstack-cli
to create the file by calling rdc add saga
.
It's possible to use redux-saga
exactly the way it's proposed in the documentation, for example you can fetch user from the server as easily as:
; const fetchUser = ; { ;}
However, this would not work because react-devstack
waits until all the tasks in sagas are resolved before sending response from the server and since takeEvery
waits indefinitely it would just hang. Therefore we have wrapped simple concept for server-side-rendering as proposed in (redux-saga docs) and very trivial implementation of takeEveryUniversal
saga is exposed.
;; const fetchUser = ; { SagaEffects;}
So just swapping takeEvery
with SagaEffects.takeEveryUniversal
from react-devstack
will do the trick.
Route based data fetching
Typical use case for any web application is fetch some data based on active route. It's very simple with react-devstack
because onEnterRouteUniversal
saga is exposed.
;; const fetchGif = ; { ;}
Now, whenever user enters /cats
route, it will automatically fetch random gif. This is of course happens on the server when user opens the app from /cats
url, and the request is sent just once (on the server), once it loads on the client, the request is not sent again, they would need to click on different link and get back to /cats
again to re-trigger API call.
react-helmet)
Custom HTML template (usingYou can use react-helmet
whenever you need in your application to control content of whole HTML. So if you just need to change title
on specific page. Just use Helmet
provided from react-helmet
:
;; const Cats = <div> <Helmet> <title>Kewl cats</title> </Helmet> <div> <h1>Cats</h1> <p>Lorem ipsum...</p> </div> </div>; ;
This will automatically work on the server as well. You can nest Helmets
as described in react-helmet docs to override default values with specifics.