Last active
October 10, 2017 18:22
-
-
Save marvinpinto/731a0d5ac87a9cc923f7779d2bc50bc2 to your computer and use it in GitHub Desktop.
Demo for Displaying a loading message while initializing a React component
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
html, | |
body { | |
display: flex; | |
min-height: 100vh; | |
min-width: 100vw; | |
background: white; | |
} | |
#container { | |
display: flex; | |
flex: 1 1 auto; | |
justify-content: center; | |
align-items: center; | |
} | |
.loading-container { | |
display: flex; | |
flex-direction: column; | |
justify-content: center; | |
align-items: center; | |
} | |
.spinner { | |
width: 40px; | |
height: 40px; | |
position: relative; | |
} | |
.double-bounce1, | |
.double-bounce2 { | |
width: 100%; | |
height: 100%; | |
border-radius: 50%; | |
background-color: #333; | |
opacity: 0.6; | |
position: absolute; | |
top: 0; | |
left: 0; | |
-webkit-animation: sk-bounce 2s infinite ease-in-out; | |
animation: sk-bounce 2s infinite ease-in-out; | |
} | |
.double-bounce2 { | |
-webkit-animation-delay: -1s; | |
animation-delay: -1s; | |
} | |
@-webkit-keyframes sk-bounce { | |
0%, | |
100% { | |
-webkit-transform: scale(0); | |
} | |
50% { | |
-webkit-transform: scale(1); | |
} | |
} | |
@keyframes sk-bounce { | |
0%, | |
100% { | |
transform: scale(0); | |
-webkit-transform: scale(0); | |
} | |
50% { | |
transform: scale(1); | |
-webkit-transform: scale(1); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<script src="https://unpkg.com/react@16/umd/react.development.js"></script> | |
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/redux/3.7.2/redux.js"></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-redux/5.0.6/react-redux.js"></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/redux-thunk/2.2.0/redux-thunk.js"></script> | |
<div id="container"></div> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const { Provider, connect } = ReactRedux; | |
const { createStore, applyMiddleware } = Redux; | |
const thunk = ReduxThunk.default; | |
const sleep = time => { | |
return new Promise(resolve => setTimeout(resolve, time)); | |
}; | |
//============ | |
// Reducer | |
//============ | |
const defaultState = { | |
isRefreshingSettings: false, | |
isRetrievingToken: false, | |
appToken: null | |
}; | |
const reducer = (state = defaultState, action) => { | |
switch (action.type) { | |
case "MAKE_REFRESH_SETTINGS_REQUEST": | |
return { | |
...state, | |
isRefreshingSettings: true | |
}; | |
case "RECEIVE_REFRESH_SETTINGS_RESULT": | |
return { | |
...state, | |
isRefreshingSettings: false | |
}; | |
case "MAKE_RETRIEVE_TOKEN_REQUEST": | |
return { | |
...state, | |
isRetrievingToken: true | |
}; | |
case "RECEIVE_RETRIEVE_TOKEN_RESULT": | |
return { | |
...state, | |
isRetrievingToken: false, | |
appToken: action.result | |
}; | |
default: | |
return state; | |
} | |
}; | |
//============ | |
// Actions | |
//============ | |
const initiateRefreshSettingsRequest = () => { | |
return dispatch => | |
Promise.resolve().then(() => { | |
dispatch({ type: "MAKE_REFRESH_SETTINGS_REQUEST" }); | |
return Promise.resolve() | |
.then(() => { | |
return sleep(600); | |
}) | |
.then(() => { | |
dispatch({ type: "RECEIVE_REFRESH_SETTINGS_RESULT" }); | |
}) | |
.catch(error => { | |
dispatch({ type: "RECEIVE_REFRESH_SETTINGS_RESULT" }); | |
throw error; | |
}); | |
}); | |
}; | |
const initiateRetrieveTokenRequest = () => { | |
return dispatch => | |
Promise.resolve().then(() => { | |
dispatch({ type: "MAKE_RETRIEVE_TOKEN_REQUEST" }); | |
return Promise.resolve() | |
.then(() => { | |
return sleep(600); | |
}) | |
.then(() => { | |
dispatch({ | |
type: "RECEIVE_RETRIEVE_TOKEN_RESULT", | |
result: "SECRETTOKEN" | |
}); | |
return "SECRETTOKEN"; | |
}) | |
.catch(error => { | |
dispatch({ | |
type: "RECEIVE_RETRIEVE_TOKEN_RESULT", | |
result: null | |
}); | |
throw error; | |
}); | |
}); | |
}; | |
//============ | |
// Application | |
//============ | |
class SampleApplication extends React.Component { | |
constructor(props) { | |
super(props); | |
this.state = { | |
initializationComplete: false | |
}; | |
} | |
componentDidMount() { | |
const { dispatch } = this.props; | |
Promise.resolve() | |
.then(() => { | |
return dispatch(initiateRetrieveTokenRequest()); | |
}) | |
.then(token => { | |
// ... do something here that pegs the main thread for a noticable | |
// amount of time - like perhaps validating the token | |
return sleep(100).then(() => { | |
return token; | |
}); | |
}) | |
.then(token => { | |
// ... now use the token to make the settings retrieval request | |
return dispatch(initiateRefreshSettingsRequest(token)); | |
}) | |
.then(result => { | |
this.setState({ initializationComplete: true }); | |
console.log("Initialization complete"); | |
return sleep(3000); | |
}); | |
} | |
render() { | |
const { appToken } = this.props.globalState; | |
const { initializationComplete } = this.state; | |
if (!initializationComplete) { | |
return ( | |
<div className="loading-container"> | |
<span> | |
<strong>Please Wait</strong> | |
</span> | |
<div className="spinner"> | |
<div className="double-bounce1" /> | |
<div className="double-bounce2" /> | |
</div> | |
</div> | |
); | |
} | |
return ( | |
<span> | |
Your token is: <strong>{appToken}</strong> | |
</span> | |
); | |
} | |
} | |
const mapStateToProps = state => { | |
return { | |
globalState: state | |
}; | |
}; | |
const store = createStore(reducer, applyMiddleware(thunk)); | |
const Container = connect(mapStateToProps)(SampleApplication); | |
ReactDOM.render( | |
<Provider store={store}> | |
<Container /> | |
</Provider>, | |
document.getElementById("container") | |
); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: Demo for Displaying a loading message while initializing a React component | |
description: See https://disjoint.ca/til/2017/10/09/displaying-a-loading-message-while-initializing-a-react-component for details. | |
authors: | |
- Marvin Pinto | |
normalize_css: no | |
wrap: b | |
panel_js: 3 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment