Once achieved angular version, this feeling with the tall on the react but wrote more code, need more configuration, pros and cons of it.
But this "navigation bar problem" is very interesting, involving in the redux to write a timer, in fact, I am very confused, in the end how to perfectly simulate the user's page load,
It seems that the browser does not provide a progress API, only in such a poor way to simulate, interested friends may wish to communicate with me.
The code is attached:
Loadingbar.jsx
import React, { Component, PropTypes } from ‘react‘;
import { connect } from ‘react-redux‘;
export class LoadingBar extends Component {
constructor(props) {
super(props); this.state = {
timer: null,
style: {
display: ‘none‘,
position: ‘absolute‘,
width: ‘0%‘,
height: ‘3px‘,
backgroundColor: ‘blue‘,
transition: ‘width 400ms ease-out, height 400ms linear‘ }
};
}
componentWillReceiveProps(nextProps) { if (nextProps.status) {
let progress = 0; this.setState({
style: Object.assign({}, this.state.style, {
width: ‘0%‘ })
});
let timer = setInterval(() => { if (progress <= (100 - nextProps.step)) { this.setState({
style: Object.assign({}, this.state.style, {
width: `${progress += nextProps.step}%`,
display: ‘block‘ })
});
}
}, nextProps.speed); this.setState({
timer: timer
});
} else {
clearInterval(this.state.timer); this.setState({
timer: null,
style: Object.assign({}, this.state.style, {
width: ‘100%‘,
display: ‘none‘ })
});
}
}
render() { return ( <div>
<div style={this.state.style} className={this.props.className}></div>
<div style={{ display: ‘table‘, clear: ‘both‘ }}></div>
</div> )
}
}
LoadingBar.propTypes = {
className: PropTypes.string,
speed: PropTypes.number,
step: PropTypes.number,
status: PropTypes.bool,
} function mapStateToProps(state) { return {...state.loading};
}
export default connect(mapStateToProps)(LoadingBar)
App.jsx
import LoadingBar from ‘LoadingBar‘;
const App = ({children}) => { return ( <div>
<LoadingBar speed={5} step={2} /> {children} </div> );
};
App.propTypes = {
children: PropTypes.object
};
export default App;
Loadingreducer.js
export default function loading(
state = {
status: false },
action = {}
) { switch (action.type) { case ‘SHOW_LOADING‘: return Object.assign({}, state, {
status: true,
}); case ‘HIDE_LOADING‘: return Object.assign({}, state, {
status: false,
}); default: return state
}
}
Loadingactions.js
export function show() { return { type: ‘SHOW_LOADING‘ }
}
export function hide() { return { type: ‘HIDE_LOADING‘ }
}
Loadingmiddleware.js
import { show, hide } from ‘./loadingActions‘; const defaultTypeSuffixes = [‘REQUEST‘, ‘SUCCESS‘, ‘FAILURE‘]
export default function loadingBarMiddleware(config = {}) {
const typeSuffixes = config.typeSuffixes || defaultTypeSuffixes; return ({ dispatch }) => next => action => {
next(action); if (action.type === undefined) { return; }
const [PENDING, FULFILLED, REJECTED] = typeSuffixes;
const isPending = `_${PENDING}`;
const isFulfilled = `_${FULFILLED}`;
const isRejected = `_${REJECTED}`; if (action.type.indexOf(isPending) !== -1) {
dispatch(show());
} else if (action.type.indexOf(isFulfilled) !== -1 || action.type.indexOf(isRejected) !== -1) {
dispatch(hide());
}
}
}
Configure Store
import { createStore, applyMiddleware } from ‘redux‘;
import { loadingMiddleware } from ‘loadingMiddleware‘;
import rootReducer from ‘./reducers‘;
const store = createStore(
rootReducer,
applyMiddleware(loadingMiddleware())
)
Configure Rootreducer
import { combineReducers } from ‘redux‘;
import { loadingReducer } from ‘./loadingReducer‘;
const reducer = combineReducers({
loading: loadingReducer,
});
Wrote a react+redux-based fake github progress bar