Create-React-CR-Project: An optimal UI-based development environment for React-Redux

Andrew Banks
DailyJS
Published in
18 min readJan 23, 2018

--

This article will present create-react-cr-project combined with causality-redux (CRPCR), which is an optimal UI-based vscode react-redux development environment. It supports all the modern webpack features out of the box and significantly simplifies the task of implementing a react-redux solution, as well as reducing the amount of code that must be written.

More specifically, the program configuration function of CRPCR automatically builds a valid react-redux program that contains all necessary library imports and other structures. The component configuration function builds a valid react MVC component with all imports and component scaffolding in place. You then only need to define the component’s state variables, service functions, component initialization and finally the associated JSX stateless react components and that is it.

In fact, these techniques of CRPCR are so efficient, that it will be demonstrated below that one can have a simple react-redux increment program up and running in just a few minutes by typing only 8 lines of code.

Moreover, components written under CRPCR are designed to adhere to the well accepted software engineering principle of MVC as described by both Microsoft and Google.

Microsoft demonstrates its support of MVC as indicated below:

When designing an application or system, the goal of a software architect is to minimize the complexity by separating the design into different areas of concern. For example, the user interface (UI), business processing, and data access all represent different areas of concern. Within each area, the components you design should focus on that specific area and should not mix code from other areas of concern.

Google gives its recommendations for MVC as follows:

We recommend that developers decouple the app into a series of independent components following the MVC pattern.

MVC offers architectural benefits over standard JavaScript — it helps you write better organized, and therefore more maintainable code. This pattern has been used and extensively tested over multiple languages and generations of programmers.

By its nature, MVC implements a separation of concerns while also promoting the reusability of the code. In addition, code written according to MVC is easier to understand and maintain. More important, MVC allows a software product to survive technology changes by requiring only a minimal coding effort to keep up with those changes.

Therefore, given the fact that CRPCR produces module scaffolding that satisfies the MVC architecture then CRPCR offers a sound development environment in terms of software engineering.

CRPCR also fully supports hot module replacement (HMR) for all of your code in the project. More specifically, while in the vscode debugger, you can add new redux state variables with initial values, add or change UI service functions and then save and those variables and functions become immediately available in the props of the react UI component without requiring a browser refresh. The redux store remains valid as well. This allows perfect code and go and fix and go react development for fast prototyping, fast development and fast bug fixing.

In addition, CRPCR provides a monitoring component written in react that displays every redux state change initiated by causality-redux. Then for any displayed redux state change, the source file(s) with the line number(s) associated with the change can be displayed in vscode with only a mouse click and key stroke. Since many programming errors result from code that incorrectly changes program state then CRPCR provides an optimal mechanism for detecting an incorrect state and then locating the source file and line number(s) that caused that incorrect change. Furthermore, future maintainers of the react project can more easily understand the program since they can quickly find the code that causes any given redux state transition.

Finally, it will be shown below that CRPCR is fully compatible with current react-redux projects by adding just a few lines of JavaScript. So, you can start using CRPCR today without disrupting your current working redux code base.

Create-React-CR-Project Features

To begin, some of the pre-configured features supported by create-react-cr-project are listed below:

  • Basic Babel ES6 (does not include the babel-polyfill), Object Rest/Spread Properties, fetch, promises, Object.assign, maps, sets and Array.from. This list can be easily extended.
  • TypeScript.
  • Supports the JavaScript standard code styling with eslint.
  • Supports the TypeScript standard code styling with tslint.
  • Vscode editing and vscode chrome extension for debugging.
  • React Hot Loading and general HMR support for all code.
  • React router.
  • React/enzyme/jsdom auto test environment with vscode debugging.
  • Dll library support for modules such as react so that these modules are pre-compiled into a DLL library since they rarely change. Then only your code needs to be compiled during development which results in much faster debug compilation.
  • CSS inline, modules and legacy support. Also support for less, sass, scss and css. Supports the postcss-loader for vendor css prefixes.
  • URLLoader support for your images, fonts etc. Inlines them in the production bundle for faster loading if they are below a user defined threshold. Also, they can be imported into your react components.
  • Minification build bundles for both css and js for production use.
  • Allows you to view your production product after a build on a simple pre-configured express server.
  • Supports material-ui react components.
  • Supports progressive web apps for production. You can opt out of this.
  • Supports development and production proxies so that you can proxy REST requests to your production server or some stub server such as the json-server.
  • UI interface to create new projects and new react components.

Implement a React Counter Program in only 8 Lines of Code

To show how easy and efficient create-react-cr-project is to use right out of the box, it will be demonstrated that we can produce and run a MVC react-redux counter program based on causality-redux by typing only 8 lines of code.

You can download create-react-cr-project and follow along with this Counter example. Also, download vscode and vscode chrome extension for debugging.

Follow these very simple instructions to install create-react-cr-project.

Once the installation completes, a project configuration UI screen will be displayed. Click the “CONFIGURE REACT PROJECT” button and the below screen will be displayed.

The default options will be fine for this exercise so simply click the “SAVE CONFIGURATION” button at the top right. The save will take some time and after that is complete, click the “EXIT” button.

Next, we will use the create-react-cr-project UI program to build the scaffolding for a Counter MVC react component. So, click the “CREATE REACT COMPONENT” button and the screen below will be displayed.

Again, the defaults are fine, so enter “Counter” for the “React component name” and then click CREATE COMPONENT”.

Exit your way out of the UI program. This creates a MVC causality-redux react component.

Next, open vscode and then open the file src/react-components/Counter/index.js. You will see the following line of code:

const counterPartition = 'counterPartition'

Causality-redux adheres to the software engineering principle of the separation of concerns when it comes to the redux store. As such, each react component state data is placed under its own unique key in the redux store by CRPCR.

For this counter example, that redux state key is 'counterPartition'. Therefore, the redux store is a set of partitions such that for each react component that requires redux state there is a redux store partition that corresponds to that component.

Now, open the file src/react-components/Counter/controller.js. Note that all the component scaffolding is in place for you. Then, locate the controller object defaultState. This object defines the shape of the redux Counter partition and the initial values for the entries in that partition. You use this object for your component state variables and their initial values.

In the defaultState object, replace the code below:

export const defaultState = {
sampleKey1: ''
}

with the following:

export const defaultState = {
counter: 0
}

This requires that only one line of code is typed.

Causality-redux uses the keys and their initial values from defaultState to construct the initial redux store partition 'counterPartition'. Those same keys are then used by causality-redux to determine which keys in the 'counterPartition' to make available in the props of the Counter component. As such, your state variables in defaultState are automatically available to your react component props without you having to take any action.

So, for example based on the above definition, in the react Counter component, props.counter will be the current value of counter in the redux 'counterPartition' partition. Note that you do not have to write a redux mapStateToProps function in order to achieve this objective. It is all done behind the scenes for you.

Next, we need to make the UI service functions available to the Counter component in order to service UI requests such as button clicks. These service functions are placed in the controller object uiServiceFunctions. All functions contained in uiServiceFunctions are automatically made available to the props of the Counter component without having to write a redux mapDispatchToProps function. So, change the code below:

export const uiServiceFunctions = {
sampleFunction1: (url) => {
partitionState.sampleKey1 = url
}
}

to the following:

export const uiServiceFunctions = {
increment: () => {
partitionState.counter++
}
}

The statement partitionState.counter++ increments the redux store value counter in the Counter partition in compliance with the rules of redux store updating. More specifically, the variable partitionState is a proxy object provided by CRPCR to all the key/values pairs in redux store partition 'counterPartition'. It returns a shallow copy of the redux store partition value at the specified key, in this case counter. On the other hand, an assignment to partitionState.key internally calls redux dispatch which then changes the value of key in the redux partition.

So, CRPCR allows you to change redux store partition values by simple assignment rather than having to code the much less efficient action creator, reducer and dispatch methods of redux.

At this point, you have typed three lines of code. Next, open src/react-components/Counter/view.jsx. Change the stateless Counter component from the below:

const Counter = (/* { sampleKey1, sampleFunction1 } */) =>
<div>
TODO: Define your component.
</div>

to the following:

const Counter = ({ counter, increment }) =>
<div>
<p>Counter: {counter}</p>
<button onClick={increment}>Increment</button>
</div>

This requires that an additional three lines of code are typed. So far, that is six lines.

Note that we are depending on the fact that causality-redux will put counter from the defaultState object in the controller and increment from the uiServiceFunctions object in the controller into the props of the react Counter component above.

Finally, open the app’s main entry point, src/react-components/MainApp/MainApp.jsx. Change the file as it is:

import React from 'react'const MainApp = () =>
<div>
TODO: Put your react component(s) here
</div>
export default MainApp

to the following. That requires you to type an additional two lines of code. Now, we are done and only 8 lines of code were typed.

import React from 'react'
import Counter from '../Counter'
const MainApp = () =>
<Counter />
export default MainApp

To run the app, simply click on the “bug” in vscode to the left and then hit the green arrow at the top left. You can check that the program does indeed work and is a react-redux solution based on causality-redux.

Now, click “Debug” at the top vscode menu and “Stop Debugging”. Down click the small down arrow to the right of the green debug button and select “Run Mocha Tests” then click the green arrow. You will see that vscode runs some test scaffolding for your component. All you need to do is add your test code in view.spec.js, controller.spec.js and possibly to model.spec.js and then create-react-cr-project runs those tests for you with no test configuration needed. Of course, the command npm run test from a command window runs those same tests as well.

The CRPCR automated test environment also includes jsdom and mounts your react app using enzyme whenever you run the tests. Therefore, you can execute tests for your UI in view.spec.js and you do not need to perform any test configuration whatsoever.

Thus, CRPCR provides an optimal environment for developing efficient modular MVC react components and their corresponding test strategies.

MVC Under CRPCR

There are various definitions of MVC and as such, this section will spell out precisely how MVC (model view controller) works under CRPCR.

Hence, each part of MVC for CRPCR is described below:

Model

  1. Contains data access methods to the server and/or local storage.
  2. Contains business logic.
  3. Performs all data formatting.
  4. The code is reusable with no program dependencies except for perhaps other business code.

View

  1. The view is generally a stateless react component (or a collection of them) that contains javascript only for the purpose of UI presentation. Note that CRPCR does not exclude the possibility that internal state in a react component may be more efficient in specific cases.
  2. The component is reusable with no program dependencies except for perhaps UI child components.
  3. Contains controller state variables in the props that are used for presentation.
  4. Contains controller UI service functions in the props that are to be connected to UI on-event handlers.

Controller

  1. The controller is the director of the component which also performs all component initialization.
  2. Defines the component’s state variables and their initial values.
  3. Responsible for all changes to the component’s state variables.
  4. Receives service requests from the UI to controller functions.
  5. Receives service requests from external sources such as web sockets or other component modules to controller functions.
  6. Possibly calls business code to complete the service requests or directly services the requests inline.
  7. Any changes made by the controller to program state that is to be displayed by the view component will cause that UI component to render.

By carefully following the above specifications, CRPCR is able to provide an environment such that one can implement a fully functioning MVC react component by only performing the following four simple steps.

  1. Define react component state keys and initial values in the controller object defaultState.
  2. Define and implement the component UI service functions in the controller object uiServiceFunctions. Also, possibly define and implement service functions to handle events that are external to the component.
  3. Define and implement your business functions that are to be called by the controller functions. In the case above for the counter component, the controller functions were simple enough not to require business code.
  4. Implement stateless react components in the view which display the state variables that are contained in the props and also wires the UI service functions that are contained in the props to the appropriate on-event handlers in the JSX react code.

Everything else is done automatically for you. Therefore, CRPCR has deconstructed the problem of developing react components into its prime components, such that you only need to write the minimum code necessary in order to implement your solution. This allows you to spend your time actually writing cool and innovative code.

In addition, each MVC react component generated by CRPCR resides in its own directory and under its own redux store key with no import dependencies on anything else in the project. Hence, CRPCR observes the software engineering principle of modularity when it comes to the MVC react components it generates.

As such, CRPCR puts you in the driver’s seat of sound software engineering principles for developing react components and then provides efficient machinery for implementing your components according to those principles.

Optimal Code and Go & Fix and Go Development

Causality-redux completely supports HMR within any part of the controller, business code and the react component. So, you can add state variables, add or change controller service functions, change business code and change anything you want in the react component then save and HMR loads all the new/changed code without requiring a browser refresh. Moreover, your redux state remains intact with HMR so you do not lose your place state wise either.

For example, run the vscode debugger on the Counter code above and hit the increment button once. Next while still in the debugger, open the file src/react-components/Counter/controller.js. Change defaultState to the following:

export const defaultState = {
counter: 0,
counter2: 12
}

So, the new redux partition variable counter2 has been added and is initialized to 12. Then change the uiServiceFunctions to the below:

export const uiServiceFunctions = {
increment: () => {
partitionState.counter += 2
},
decrement: () => {
partitionState.counter--
}
}

Hence, the increment function has been “broken” to increment counter by 2 and a new controller service function decrement has been added. Then save. Finally, change the react Counter component to the below:

const Counter = ({ counter, counter2, increment, decrement }) =>
<div>
<p>Counter: {counter}</p>
<p>Counter2: {counter2}</p>
<button onClick={increment}>Increment</button>
<button onClick={decrement}>Decrement</button>
</div>

Then save and you will see the component displays Counter: 1 and Counter2: 12. Therefore, we have added a new state variable counter2 to the redux store partition and HMR with causality-redux adds this new state variable to the props while at the same time, counter remains correct at a value of 1.

Next, click the increment button and note that it increments counter by 2 now. Then click the decrement button and counter decrements by one. So, we have both changed a controller UI service function and added a new one and causality-redux adds these to the props of the component while maintaining the current redux state. All you had to do was code and save.

Thus, with CRPCR you can code and go while remaining in the debugger and all your new additions and changes will be picked up on a save. This enables fast prototyping as well as instant feedback with your code as you develop your react component. In fact, the code and go of CRPCR is an efficient implementation of the software engineering principle of incrementality.

Moreover, since you can fix your controller functions and UI component while in the debugger then CRPCR also provides optimal fix and go debugging while maintaining your current redux state.

Causality-Redux StateMonitor

Many bugs are caused by code that incorrectly changes the program’s state. Therefore, an optimal software engineering environment would provide you the tools to quickly identify the incorrect state change and then quickly go to the source code and line(s) that caused the incorrect state change. This is exactly what CRPCR provides.

To show this, exit the debugger and download the react StateMonitor component. Also, download the vscode extension cr-state-file-open and follow the simple installation instructions.

Then simply add the monitor component to the directory src/react-components with its code under the directory src/react-components/StateMonitor and modify src/react-components/MainApp/MainApp.jsx to the following:

import React from 'react'
import Counter from '../Counter'
import { StateMonitor } from '../StateMonitor'
const MainApp = () =>
<div>
<StateMonitor />
<Counter />
</div>
export default MainApp

Then by using the StateMonitor, you can identify where state is incorrectly changed in your program.

For example, using the latest changes above for the Counter component, restart the vscode debugger and click the increment button once. See the image below of the StateMonitor after one click of the increment button.

As you can see, the monitor records state changes made by the UI service function increment. So, since we want the increment button to add one to the counter redux state variable then counter=2 is an incorrect state. Click on that entry and the line number and source module where that state change was made are displayed . See the image below.

The entire space below the Change Keys heading is for listing all the key/value pairs in the partition that were changed at this program state change. In this case, only counter changed in the redux partition 'counterPartition'.

Next, go to vscode and bring up the command palette as shown in the gif image below. Choose the ‘react-causality-redux load file’ entry. Vscode and the cr-state-file-open extension bring up the appropriate source file with the line that caused the incorrect state change highlighted on screen. See the line partitionState.counter += 2 below. Then fix the bug and save.

Obviously, this is an important advancement for debugging state changes and for maintaining react components.

For the case above, there was only one source file on the call stack that caused the state change.

However, it may be the case that several of your source files are responsible for some change in state. In that situation, vscode will display your call stack items and allow you to pick from among them. Then as long as you do not change the clipboard, you can continue to bring up the command palette and choose the ‘react-causality-redux load file’ extension and then pick any file on the call stack. Vscode will bring up that file and highlight the source line that was responsible for causing the state change. See the gif image below.

Note that library files are excluded from the call stack since you cannot change those files while in the debugger and also apply HMR.

Now getting back to the counter example, many steps may had taken place to get to that point where the bug happened. The monitor allows you to set the redux state to conditions just before the error took place and then you can proceed correctly from there. To show this, click X at the top right to remove the detail screen and then click the green arrow on the monitor and the following is displayed.

Click the entry where the state was last correct as shown below.

Then click the blue down arrow at the top to set the redux store back to this correct state. At that point, the bug is fixed, the fixed code is HMR loaded and the redux state is set to the first correct state before the bug. Now, you can continue without having to repeat all the steps that occurred before the error. Thus, CRPCR provides an optimal technique for quickly identifying incorrect state changes and then quickly locating the source file and line where the state change happened so that the code can be easily fixed.

React-Redux Integration

Causality-redux is fully compatible with redux since it is an extension of the redux store. To integrate causality-redux, first perform the following in your react-redux project.

npm install -—save causality-redux react-causality-redux

Then simply add the code steps below and all of your existing redux code will be valid and you can begin coding using causality-redux without affecting your existing redux code base. NOTE: the redux store must be created before any causality-redux components are imported.

import causalityRedux from 'causality-redux'
import 'react-causality-redux'
// Create the redux store as normal. These two steps below must be // done before any causality-redux react components are imported.
const rStore = createStore(combineReducers(yourCoreReducersObject), hydrateState)
causalityRedux.setReduxStore(rStore, yourCoreReducersObject)

If your hydrateState contains causality-redux state then do the below instead.

import causalityRedux from 'causality-redux'
import 'react-causality-redux'
// Create the redux store.
const rStore = createStore(causalityRedux.combineReducers(yourCoreReducersObject), hydrateState)
causalityRedux.setReduxStore(rStore, yourCoreReducersObject, hydrateState)

If you use redux code splitting or some type of lazy load module based logic for reducers then perform the step below with your additional reducers that are to be added and abandon your current lazy load method. This will add the additional reducers to the existing redux reducers.

causalityRedux.addReducers(additionalReducersObject)

Therefore, no matter how your current react redux solution is structured causality-redux can be integrated with it in just a few lines of code.

Conclusions

This article presented several important innovations within CRPCR such as a react UI interface for building react projects and react components, default MVC scaffolding for react components, the implementation of react components as an abstraction consisting of state, service functions and UI presentation, code and go and fix and go development based on the adherence of CRPCR to HMR and state change to source code/line number mappings so that one can quickly identify and locate state change errors and their associated code.

Further, it was shown that react-redux solutions developed under CRPCR are more efficient, require much less code and are easier to understand and maintain when compared to usual react-redux solutions. Moreover, CRPCR adheres to modern software engineering principles such as MVC, the separation of concerns, the anticipation of change, abstraction and incrementality. Therefore, CRPCR operates according to well accepted and sound principles of software engineering.

Finally, CRPCR is fully compatible with current react-redux projects by adding just a few lines of code. Thus, you can start using CRPCR today without disrupting your current working redux code base.

So, take a few minutes to download CRPCR and you will agree that you are much more productive developing react-redux solutions by using CRPCR.

⬇️ Downloads:

Vscode
Vscode chrome extension for debugging
Create-react-cr-project
Redux State Monitor
Vscode Extension to Quickly Display the Source File and Line Number(s) of any Given State Change

📘 Further Reading:

Google MVC
Microsoft MVC and Additional Software Engineering Principles

--

--