React Redux - development notes
Bài đăng này đã không được cập nhật trong 6 năm
Among the JavaScript frameworks React is becoming popular these days. Apparently the ease of maintenance (due to markup and view logic unification), isomorphism (the ability to run on both client and server end) and certainly the concept of virtual DOM is behind it's popularity. JSX is a OOP language that can be used with React which speeds up the development a lot. It's not a must and can be avoided with the penalty of some extra hours of coding every time.
Redux on the other hand is a nice fit for React, which handles the React states efficiently with a single state tree architecture. While the combination of React and Redux is great, it's learning curve is quite steep. In the wild, there are informations available on them both, but, none of them provides a smooth guided path. Some are too advanced while others make it difficult to understand the simple thing by using ES6, package management modules and dependencies and a lot's of files.
This article will provide some note on React, Redux, ES6 and package management in a concise manner. It will not show a route in understanding React or Redux from the scratch, but will act as a very concise reference.
React
The formal definition expresses React as,
A JS library that provides view for data rendered as HTML
React in general
- Component based: Components are encapsulated thingies.
- Can render on server using Node. (potentially this feature can be used in React Native)
React building blocks
-
render(component, mountNode)
method takes input and returns displayable. To simplify,render
takes the ELEMENT(s) that needs to be displayed, and the LOCATION (mountNode) where to display -
Element is the reacts representation of a tag and it's contents. In pure JS, the element could be created using
React.createElement
function, where in JSX a simplified and custom tag like representation is used. -
Controlled vs Uncontrolled components:
- Controlled component includes a
value
prop which reflect the element value. AnonChange
event could be used to updatevalue
in response to user input throughsetState
. - Uncontrolled component doesn't have a
value
prop and any input will immediately reflect the rendered element. But, nonetheless, updates could be listened the same way usingonChange
and and a default value can be set withdefaultValue
ordefaultValue
prop. - These components (e.g.
<input>
,<select>
) can be of different types, that can be expressed to React usingtype
prop. (e.g.type="(text|checkbox|radio)"
)
- Controlled component includes a
-
State identification: In order to add interactivity to the React components it is necessary to identify states. And, later it is needed to identify the components that owns (mutates) these state. This is probably a good guideline for state owner preparation.
-
By design, react props are considered read only. They (
this.props
keys) should never be manipulated. -
Single root: React components can only have a single root.
-
By convention, custom React class names begin with an uppercase letter, where native HTML element names start with a lowercase letter.
-
Some significant React specific methods (including lifecycle methods) for fast startup:
- Mounting
getInitialState
componentWillMount
componentDidMount
- Updating
componentWillReceiveProps
shouldComponentUpdate
componentWillUpdate
componentDidUpdate
- Unmounting
componentWillUnmount
- Helpers
forceUpdate
getInitialState
setState(data, callback)
propTypes
-getDefaultProps
- Mounting
-
ref
is a special attribute that can be attached to anything returned fromrender
.- Value of
ref
can be a "callback function" or a "string"-
callback function: executes as soon as the associated component is mounted. The referenced component is passed as a parameter of the function.
-
string: can be used as a reference to the associated component. An usage should look like
this.refs.comp_name
. It is a considered legacy and should be avoided in new codes. A compatible way of extracting reference can be performed with "callback function" using the following syntax.ref={ref => this.comp_name = ref}
-
- Value of
-
props.children
: This holds all the children components that the reference component may have. When there is a single child, the child itself it returned, not the array. For example, callingthis.props.children
over<CompX>Data</CompX>
will returnData
which is of typeString
. -
Single responsibility principle is a development principle that suggests that a single class (or in our case, component) should do a single thing only. This also implies that when necessity arises, it should be decomposed into smaller sub-components.
-
State in React is the explicit representation of an app. It makes an app predictable. State may include a large variety of data from a single input element's state to the state of an entire cloud spreadsheet.
-
"state" should contain data that event handlers may change to trigger a UI update. All data that can be computed or retrievable from current state should be excluded.
-
Owner-ownee and parent-child relationship: #link
-
React class definition can be accomplished in three different ways
-
React.createClass
functionExample
// Simple way React.createClass({ render: function() { return ( <div>A simple react component</div> ); } }); // Using ES6 object shorthand React.createClass({ render() { return ( <div>Another react component</div> ); } });
-
ES6 class
Example
class MyComponent extends Component { render() { return ( <div>Yet another react component</div> ); } }
-
JS function / ES6 arrow
Example
const MyComponent = () => <div>A tiny component</div>;
-
Redux
It can be expressed as
- Predictable state container
- State: Different phases of the UI that cannot be calculated, duplicated or generated from the available dataset. State may include different user interactions and environment changes (e.g. network request) that may occur during the life-cycle of an application.
Redux building blocks
- Reducer is the pure function of previous state and action that returns next state. Reducers are accumulated in store. Store methods,
getState
- Returns current statedispatch
- Dispatches an actionsubscribe
- Subscribes a callback for the store. When an action is dispatched, the subscribed callback will be called.
- Pure function
- Calculates a result in response to the provided arguments
- Doesn't modify the arguments
- Doesn't modify any other components (e.g. make network request or DB update)
- Predictable (same set of results for the same set of arguments)
- Example: Reducer
- State is an object tree, representing different states of an application. The state of an application is stored in an object tree within a single store. State should be considered read only and should only be manipulated through action dispatch.
- Action is a plain object that includes,
action_type
andchanges
oraction specifics
(e.g. entry index, filter_name). It must have atype
property. - Action Creators are the functions that create actions. There is also bound action creator that automatically dispatches.
- Store Only a single store is possible. For multiple data handling logics (reducers) reducer composition can be used with
combineReducers()
function which in turn can be passed to the store. Store can be created usingcreateStore()
function where a second argument can be optionally passed as initial state.- The
subscribe()
method returns a function for unregistering the listener. - Calling
rootReducer.dispatch(action)
invokes all the reducers. - When state changed, every subscribed listeners to the store are called.
- The
- Presentational and Container Components
This distinction between component types is for several benefit, where the prime cause is concern separation between view and data and extending re-usability.
- Presentational Component: Like the name suggests, these are usually the components that are used to represent UI blocks. These are not aware of Redux.
- Interacts with the application by means of props. Any intent of changing state is expressed by callbacks.
- Container Component: These components usually provide data to the presentational components (tasks like
data fetching
,state updates
).- Subscribing listeners and dispatching actions are the responsibility of container components
- Presentational Component: Like the name suggests, these are usually the components that are used to represent UI blocks. These are not aware of Redux.
- What Redux basically does is, it provides objects called "action" to mutate data instead of letting app. codes directly mutate the data.
- Redux implementation is possible not only in React but also in Angular, Amber, jQuery or Vanilla JS. But since, it's about state, it works well with React (cause React represents UI as a function of state, and Redux emits state updates in response to actions).
- Dispatching actions can be done using
store.dispatch()
, and also withconnect()
. Multiple action creators can be bound together usingbindActionCreators()
. - Resolving complexities
- Presentational components are totally independent from Redux. They receives data via props and utilizes them. They are connected to React through Containers.
- Container components are technically just React components that uses
store.subscribe()
to read a part of the state tree and supply props to a presentational component it renders.- All the container component needs access to the Redux store. There are two ways
-
Manual way is to pass store as props to all the parent components along with the target container component
-
Redux way is to use Redux component
<Provider>
during root component render.<Provider store={store}> <App /> </Provider>
-
- All the container component needs access to the Redux store. There are two ways
Testing and method generation in redux
- Testing libraries: Expect
- In order to generate pure (non-mutating) method, write test case (using Expect) and deep freeze arguments prior to any ops in the test case.
Package Management and ES6 support
Babel
- Necessity: The new Javascript ( ES2015 / ES6 ) features are not readily available on browsers. If ES6 code is used, then it need to be compiled to the standard JS code that browsers support. Babel is the compiler that does this job.
- Modes: Babel compiles new JS to old JS but provides a large scale flexibility in doing so. It supports
- On the fly compilation
- Pre-compilation
- Configuration: Babel expects a
.babelrc
file in the project root, that includes preset and options. - Installation
Installation can be global or local (project specific), although, global installation is discouraged (cause, different project may use different babel version which will increase the chance of a clash).
-
Local installation
// In a npm project folder npm install babel
-
Global installation
npm install -g babel
-
Manual compilation
babel to_convert.js -o output.js
-
Webpack
-
An open-source JS module bundler. It receives modules with dependencies and generates static assets that represents those modules.
-
Webpack can also generate dependency graph to use in the development phases.
-
Webpack natively can only handle JS. For css support
css-loader
(to process CSS files) andstyle-loader
(to apply CSS) loaders are required. -
Webpack basic Configurations
Installation
npm install webpack -g
Considering current project has
entry.js
(compilable) andindex.html
, whereindex
expectsbundle.js
(compiled)The simplest build can be produced as shown below
webpack ./entry.js bundle.js
CSS support is not built-in in Webpack, so support can be achieved through
css-loader
andstyle-loader
modules like this:Installation
npm install css-loader style-loader
Preprocessing,
require("!style!css!./style.css");
This is a piping syntax that implies that specified CSS is to be processed through
css-loader
first and thenstyle-loader
.It is also possible to bind loaders with regex as follows,
Method 1: CLI
webpack ./entry.js bundle.js --module-bind 'css=style!css'
Method 2: Config file
# TODO: PROVIDE EXAMPLE
-
Configuration file: Webpack expects a
webpack.config.js
in CWD. -
Auto-compilation can be achieved through the CLI
--watch
switch. -
Development server support is available which can be achieved by installing through
npm install webpack-dev-server -g
and running as ordinary CLI tools. It features,- Auto-compilation
- Browser reload on server (client server) updates.
CommonJS
- CommonJS is a runtime ecosystem specification that resolves the dependency issues of JS running on environments other than browser.
- CommonJS provides,
-
require()
: Which is a function that allows to import a module in the referring scope.var SOMETHING = require("./something")
-
module
: It's an object that allows to export something from the current scope.module.exports = SOMETHING;
-
JS primers
Scattered info
-
Object.assign(target, ...sources)
method can be used to create a manipulated version of the source objects.var src_obj = {x: 1, y: 2, z: 3}; var ref_to_tgt = Object.assign({}, src_obj, {y: 5}, {z: 55}); // ref_to_tgt // {x: 1, y: 5, z: 55};
-
Concern seperation
: When a single function appears to be handling more than one concern, extract different functions from it to handle specific actions.
ES2015 Features
Major feature includes,
- Arrow function and lexical this: Arrow functions share the same lexical
this
as their surrounding code. - Class: Class supports prototype-based inheritance, super calls, instance and static methods and constructors
- Enhanced object literals
- Template string
- Destructuring
- Computed object properties
let
andconst
Lot's of info
All rights reserved