react-ele-webapp
Project address: https://github.com/kliuj/reac...
run
Download the project
npm install
Then
npm run dev is enough
The project based on react-router Redux is mainly for learning actual react. Data are fixed, temporarily grasped from the hungry interface, simulated a 0-100ms asynchronous data delay, thank you hungry?
The following are the process of project development and some reflections, according to which at least a relatively complete react family bucket project can be guaranteed.
Content reference
react document: http://reactjs.cn/react/docs/...
react-router document address: https://reacttraining.com/rea...
Chinese version of react-router Reference: http://www.uprogrammer.cn/rea...
Reux Document Reference: http://redux.js.org/
Reux Chinese Documents: http://cn.redux.js.org/
Construction project:
Create project directory, install package.json, configure webpack.config
Do a good job of basic dependency, extracted from package.json
"devDependencies": { "babel-core": "^6.23.1", "babel-loader": "^6.4.0", "babel-preset-es2015": "^6.22.0", "babel-preset-react": "^6.23.0", "html-webpack-plugin": "^2.28.0", "jshint": "^2.9.4", "jshint-loader": "^0.8.4", "react": "^15.2.0", "react-dom": "^15.2.0", "react-router": "^2.0.0", "redux": "^3.6.0", "webpack": "^2.2.1", "webpack-dev-server": "^2.4.1" } //JAVASCRIPT
Project Module Structure Organizes Some Basic Work
Beginning the development of a project in addition to technical selection, there are many basic things to be designed, a good organizational design can improve work efficiency in the future. I still have many shortcomings in this respect. At present, I mainly consider the design of three modules:
1: Background Interface Communication Layer: model.js mainly deals with the request sending and callback of unified interface. Putting them together is more conducive to later maintenance and also increases readability.
//The url corresponding to the interface, just for demonstration const uris = { index_entry : fetchData.index_entry, hot_search_words : fetchData.hot_search_words } //Interface Call Layer export default function send(url,postData,successCallback,errCallback){ //Analog Delay, False Interface let promise = new Promise(function(resolve,reject){ setTimeout(function(){ resolve(fetchData[url]) },Math.random()*100) }) promise.then(function(data){ successCallback(data) }) }
2: Local Data Cache Maintenance: baseStore.js mainly deals with jump-back between pages, increasing more autonomy and extensibility
// Automatic Storage of Browse Records export function saveFrom(prop) { let name = prop.pagename, transit = prop.location, qhfrom = transit.query.qhfrom ,//Return to home page by default para = transit.query.para ? JSON.parse(transit.query.para) : ''; if(!qhfrom) return false; let paths = localStorage.getItem("FromUrlStore") ? JSON.parse(localStorage.getItem("FromUrlStore")) : {}; if (localStorage) { paths[name] = { 'name':qhfrom,//Storage source pages 'para':para //Store source page parameters } localStorage.setItem("FromUrlStore", JSON.stringify(paths)); } } //Storage page source, unified management
3: Processing of Common Methods: baseFun.js is mainly used to define some common module methods.
//Placing Common Functions export function showToast(){ ... }
Initialize pages using react-router
import React from 'react' import { render } from 'react-dom' import { Router, Route, Link,hashHistory ,IndexRedirect,IndexRoute} from 'react-router' import Home from './components/home.jsx' import Discover from './components/discover.jsx' const App = React.createClass({ render() { return ( <div> <footer> <Link to="/home">Take-out food</Link> <Link to="/discover?qhfrom=home">find</Link> </footer> {this.props.children} </div> ) } }) const route = ( <Router history={hashHistory}> <Route path="/" component={App}> <IndexRoute component={Home} /> <Route path="home" component={Home} /> <Route path="discover" component={Discover} /> </Route> </Router> ) render(route, document.getElementById("app"))
A brief introduction to the code:
Because there is no background, hash History (hash routing) is adopted. For hash routing, you can refer to: https://github.com/kliuj/spa-... There is a brief introduction.
This is router's jump <Link to="/home">takeout </Link> This is the load subrouting component {this.props.children} This is the default jump page <IndexRoute component={Home}/>.
Processing scrolling lists on the home page
The home page is divided into four components.
Bottom Navigation + Scroll List + Single Product + Home Search Box
The scrolling list encapsulates a simple component
<List list={Pro}// Each product item component Page name = {'home'}// Jump the upper page of the product list to process the return data={this.state.productList} // / Data to be rendered onScroll = {this.getMore.bind(this)}// rolling load function /> In the scrollList component, the scroll event is monitored for automatic loading.
react-redux handles login and logout
Reasons for using redux: User information and login are two different components, and there is no parent-child relationship, but data state sharing and interaction are required. Detailed information can be seen in the official documents above, I will briefly talk about the application of my project here.
Define constant actionTypes.js
//Login successfully export const LOG_SUCCESS = 'LOG_SUCCESS' //Logging in export const LOG_ING = 'LOG_ING' //Logout login export const LOG_OUT = 'LOG_OUT' //Mainly the name corresponding to the Unified Preservation State
Define specific trigger actions/login.js
//Logout Synchronization export function log_out (){ return { type:actionTypes.LOG_OUT } } //Login Asynchronism export function log_in (obj){ return dispatch=>{ //The status of pending being logged in dispatch({type:actionTypes.LOG_ING}) //Start sending asynchronous requests for login new Promise((resolve,reject)=>{ ... }).then(res=>{ dispatch(res) }) } } //Asynchronous state requires Middleware
Processing data reducers/login.js
export default function(state = initialData,action){ switch(action.type){ case actionTypes.LOG_SUCCESS: return { loginstate:1, username:action.username } break case actionTypes.LOG_ING: return{ loginstate:-1, username:'Logging in' } case actionTypes.LOG_OUT: return initialData break default : return initialData } }
Creating store Layer store/store.js Using Middleware
import {createStore, applyMiddleware} from 'redux' import thunk from 'redux-thunk' //Merged multiple reducer s, decoupling import rootReducer from '../reducers/index.js' const middlewares = [thunk] const createStoreWithMiddleware = applyMiddleware(...middlewares)(createStore) export default function configureStore(initialState){ return createStoreWithMiddleware(rootReducer,initialState) }
Introducing in Routing Layer
import {Provider} from 'react-redux' const store = configureStore() const route = ( <Provider store={store}> <Router history={hashHistory}> ... </Router> </Provider> )
Use in components
import { connect } from 'react-redux' import {log_out} from '../../actions/login.js' //operation ... ... function mapStateToProps(userinfo){ let {login} = userinfo //This is all the reducers returned, and we only use what we currently need to refer to the reducers/index.js content. return login } export default connect(mapStateToProps)(UserInfo) //This login data can then be retrieved from this.props in the current component state. //Operational time const {dispatch} = this.props; dispatch(log_out()) //At this point, you can manipulate the data in redux state, and each data change is sent to all received components.