React such a popular framework is not introduced, Redux is a small frame of a single data flow, of course, not only with react, it was originally for the react, and now for all, such as Ng-redux project. Redux as the standard collocation of react, a lot of momentum beyond flux. Today show an example to get started redux. source code here. (This article by default you already have React Foundation, ES6 Foundation)
This effect is very simple is a count, +++++ button click Will +1;input inside what to write, submit will alert what content, this demo is very messy, I modified the official counter example, add some experimental things, More suitable for familiar with Redux this thing.
As we all know, react is composed of components, each component is not related to the other, the data is passed through the props. The single data stream implemented by Redux is tailored for react. It maintains a store, handles things, business logic, data in this store, sees it as a data-manipulation object, and this thing treats it as a props incoming react component, and then it can be used to display and manipulate the data. This react component is similar to the usual react component, but the processing data is handled using the store, which is the incoming props. For a detailed tutorial please poke Redux Chinese API.
1. First look at the HTML of the homepage, very simple, nothing. Inside this UL actually does not have what use, hahaha. In fact, is a div, inside the things let react processing. Introduction of a Bundle.js (Webpack compressed file)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>react+redux</title>
</head>
<body>
<div id="root">
<ul>
<li>l1</li>
<li>l2</li>
<li>l3</li>
<li>l4</li>
<li>l5</li>
</ul>
</div>
<script type="text/javascript" src="bundle.js"></script>
</body>
</html>
2. Mainly the code in main.js
import {render} from "react-dom"
import React from "react"
import {Provider} from "react-redux"
import configureStore from "./store/configureStore"
import App from ‘./containers/app.js‘
const store =configureStore();
render((
<Provider store={store}>
<App />
</Provider>
),document.getElementById(‘root‘));
Let's see what it did. Introduced render, React, Provider, and the configuration store-configureStore written by myself, as well as the component App processed by redux. Render is just the way of writing in es6, it can also be replaced by the usual reactive, not listed. The Provider doesn't have to worry about it. It only knows that redux just writes the component. It passes the store created by itself to the react component, and then throws the processed App component there, and it's over. Mainly we look at how its store was created, and how the App handles it.
3. First look at how the store is handled. Here is /store/configureStore.js
import {applyMiddleware,createStore} from "redux";
import thunk from "redux-thunk";
import reducer from "../reducers/reducer.js"
const createStoreWithMiddleware=applyMiddleware(thunk)(createStore)
export default function configuerStore(initialStore){
const store=createStoreWithMiddleware(reducer,initialStore);
return store;
}
It introduces the middleware thunk, the specific role is to let the action through the processing of the function, this middleware is said to be less than 10 lines. See the tutorial linked above for details. You can see the function createStoreWithMiddleware(reducer, initialStore) that creates the store; the incoming reducer and the initialStore. The initialStore is the initial Store state, and you can take the structure randomly. For example, the store in this example has only one count field, which is used to store the count number. The reducer is an important point. It is the place to execute business logic. It is a pure function, and the result is constant at any time (incoming the same thing).
4.reducer /reducers/reducer.js"
import {combineReducers} from "redux"
import { ADD,RED } from ‘../actions/action‘
function counter(state=0,action){
switch(action.type){
case ADD: return state+1;
case RED:return state-1;
default:return state;
}
}
const rootReducer=combineReducers({
counter
})
export default rootReducer;
The combineReducers also do not care, he is a combination of multiple reducer, used to split the business. The reducer is a thing to change the data. The function of this counter is a reducer. It operates the state by looking at the value of the type of the action. If the type of the action is ADD, the state is +1, which is RED-1. It's a pure function, no matter when you pass in the same action, its output will not change. What is this action?
5.action actions/action.js
export const ADD="ADD"
export const RED="RED"
export function increment(){
return {
type:ADD
}
}
export function decrement(){
return {
type:RED
}
}
export function ince(){
return (dispatch,getState) =>{
//const {counter}=getState()
dispatch(increment());
}
}
export function dece(){
return (dispatch,getState)=>{
//const {counter}=getState()
dispatch(decrement())
}
}
For the sake of simplicity, I changed the action of the official website example, leaving two actions added and subtracted. What is it? How do you change the data depends on it, it defines the ADD, RED two constants, as type, redux specifies that the action must have a type attribute, and it does not matter. Redux provides only a few APIs, including dispatch and getState. dispatch is the only api that changes state. getState is the current state, so dispatch(action) is the method to change the current state. We want to increase count, which is dispatch(increment( )); we encapsulate it into the ince() and pass it to the component so that it can change the state directly, that is, execute the ince() every time you click +++++.
To sum up, this is the entire store, it creates a store, passed in the reducer (how to act according to the action data), the reducer contains the action (change what data, how to change). Pass this store to the component App, you can change the count through the method inside props.
6. Redux modified components
Look at the main.js inside the packaged app directly, we see how it handles App /containers/app.js
import {bindActionCreators} from "redux"
import {connect} from "react-redux"
import App from ‘../component/App.js‘
import *as Actions from ‘../actions/action‘
function mapStateToprops(state){
return {
counter:state.counter
}
}
function mapDispatchToProps(dispatch){
return bindActionCreators(Actions,dispatch)
}
export default connect(mapStateToprops,mapDispatchToProps)(App)
bindActionCreators, the only scenario that uses bindActionCreators is when you need to pass the action creator down to a component, but you don't want the component to be aware of the existence of Redux, and you don't want to pass the Redux store or dispatch to it. It encapsulates all the actions. bindActionCreators put action on the layer
The App component here is the normal react component, and the way to modify it is connect. Let's see what connect did.
Connect passes two functions to the argument, the name of the first argument, mapStateToprops, is also very clear, you need to put what in the state into the props, here only the counter one field. The second mapDispatchToProps, the dispatch is passed to props, so that the component can call dispatch to change the structure of the data. However, there is bindActionCreators, there is no dispatch, and we also encapsulate the ince() in the action, which is the action added by dispatch. And don't use dispatch.
Transfer the data, how to modify the data to the props, and then you can use it.
Finally, look at the App component, how to use the data and how to modify the data?
7.APP /component/App.js
import {render} from "react-dom"
import React from "react"
class App extends React.Component {
constructor(props){
super(props);
this.handleClick=this.handleClick.bind(this);
this.onSubmit=this.onSubmit.bind(this);
}
handleClick(){
const {ince,dece,counter} = this.props;
ince();
}
onSubmit(event){
alert(this.refs.text.value);
}
render() {
const {ince,dece,counter} = this.props;
return(
<form onSubmit={this.onSubmit}>
<input ref=‘text‘ type="text" />
<div>{counter}</div><input type="button" onClick={this.handleClick} value="++++++++++" />
<button>submit</button>
</form>
)
}
}
class Bpp extends React.Component{
render(){
return (
<div>{this.props.fuk}
</div>)
}
}
class Cpp extends React.Component{
render(){
const {ince,dece,increment,decrement,counter} =this.props;
const id=this.props.params.id
return (
<div>this is cpp id为{id}</div>)
}
}
export default App;
Bpp and Cpp are not shown, just for experimentation, and deleting is fine. (I just forgot to delete it)
The components written here are written in es6. Es6 encapsulates the native js prototype operation, however it is an incomplete syntactic sugar, because the property cannot be written inside, and the public property does not work.
Introduced React, render is equivalent to ReactDOM.render. The component inherits React.Componet with the extends keyword. In fact, you can also use React.createClass, which is actually the same. The latter is still used by many developers of the developer, because it is more convenient, it is more convenient to say, and later mentioned.
Take a look at this jsx, which is a form form, a commit trigger event, an input box, a +++++ button, and a div with {counter}, which displays the data.
It is worth mentioning that const {ince,dece,counter} = this.props; take out the things passed by props. What to take out? Data and how to modify the data. Here only the ince and dece are taken out. They are our encapsulated actions. Dispatched inside, you can use it to manipulate data directly. Counter is our data, which is displayed in the div {counter}.
onSubmit={this.onSubmit}, submit executes its own defined event, popping the value of this.refs.text, which is the value of input.
Also note that there is something inside the constructor, this thing is executed when the class inherits, super (props); is a must, if you do not write will automatically add to you, is to execute the parent class this . To be careful of
this.handleClick=this.handleClick.bind(this);
this.onSubmit=this.onSubmit.bind(this);
These two must be bound to this, otherwise you can not get this in these two functions, this is very pit, and it is very troublesome. In addition, the class function of es6 is not perfect. Some places can't replace the prototype operation of js. This also makes it very easy for developers to write with React.createClass. Component lifecycle events can also be used directly. Naturally, it is more convenient.
In summary, this is the code for the entire example,
Here is a picture of the main program is divided into two parts: create store and decorate app. The main program main.js gets them together and completes the example of react-redux. Some of the apis used in it are not explained in detail. For details, see the link to the redux Chinese api given above.
There is no complicated tool in webpack, just use babel to convert es6, nothing else.