लक्ष्य
जब html पेज रेंडर किया जाता है, तो तुरंत एक स्पिनर प्रदर्शित करें (जब रिएक्ट लोड होता है), और रिएक्ट तैयार होने के बाद इसे छिपाएं।
चूंकि स्पिनर शुद्ध एचटीएमएल / सीएसएस (रिएक्ट डोमेन के बाहर) में प्रदान किया जाता है, रिएक्ट को सीधे दिखाने / छिपाने की प्रक्रिया को नियंत्रित नहीं करना चाहिए, और कार्यान्वयन को रिएक्ट के लिए पारदर्शी होना चाहिए।
समाधान 1 -: खाली छद्म वर्ग
चूँकि आप DOM कंटेनर में प्रतिक्रिया प्रदान करते हैं - <div id="app"></div>
, आप उस कंटेनर में एक स्पिनर जोड़ सकते हैं, और जब प्रतिक्रिया लोड और रेंडर करेगी, तो स्पिनर गायब हो जाएगा।
प्रतिक्रिया रूट के अंदर आप DOM तत्व (उदाहरण के लिए div) नहीं जोड़ सकते हैं, क्योंकि प्रतिक्रिया के रूप में जैसे ही कंटेनर की सामग्री को प्रतिस्थापित किया जाएगा ReactDOM.render()
। यहां तक कि अगर आप प्रस्तुत करते हैं null
, तब भी सामग्री को एक टिप्पणी द्वारा बदल दिया जाएगा - <!-- react-empty: 1 -->
। इसका मतलब यह है कि यदि आप मुख्य घटक की गणना करते समय लोडर प्रदर्शित करना चाहते हैं, तो डेटा लोड हो रहा है, लेकिन वास्तव में कुछ भी प्रदान नहीं किया गया है, कंटेनर के अंदर रखा गया लोडर मार्कअप ( <div id="app"><div class="loader"></div></div>
उदाहरण के लिए) काम नहीं करेगा।
एक वैकल्पिक हल स्पिनर वर्ग को प्रतिक्रिया कंटेनर में जोड़ना है, और :empty
छद्म वर्ग का उपयोग करना है । स्पिनर दिखाई देगा, जब तक कि कुछ भी कंटेनर में प्रदान नहीं किया जाता है (टिप्पणियां गिनती नहीं करती हैं)। जैसे ही प्रतिक्रिया टिप्पणी के अलावा कुछ और प्रदान करती है, लोडर गायब हो जाएगा।
उदाहरण 1
उदाहरण में आप एक घटक देख सकते हैं जो null
तैयार होने तक प्रस्तुत करता है । कंटेनर लोडर के रूप में अच्छी तरह से है - <div id="app" class="app"></div>
और लोडर का वर्ग केवल तभी काम करेगा जब यह :empty
(कोड में टिप्पणियां देखें):
class App extends React.Component {
state = {
loading: true
};
componentDidMount() {
// this simulates an async action, after which the component will render the content
demoAsyncCall().then(() => this.setState({ loading: false }));
}
render() {
const { loading } = this.state;
if(loading) { // if your component doesn't have to wait for an async action, remove this block
return null; // render null when app is not ready
}
return (
<div>I'm the app</div>
);
}
}
function demoAsyncCall() {
return new Promise((resolve) => setTimeout(() => resolve(), 2500));
}
ReactDOM.render(
<App />,
document.getElementById('app')
);
.loader:empty {
position: absolute;
top: calc(50% - 4em);
left: calc(50% - 4em);
width: 6em;
height: 6em;
border: 1.1em solid rgba(0, 0, 0, 0.2);
border-left: 1.1em solid #000000;
border-radius: 50%;
animation: load8 1.1s infinite linear;
}
@keyframes load8 {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.4.1/react.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.4.1/react-dom.js"></script>
<div id="app" class="loader"></div> <!-- add class loader to container -->
उदाहरण 2
:empty
चयनकर्ता को दिखाने / छिपाने के लिए छद्म वर्ग का उपयोग करने पर एक भिन्नता , स्पिनर को ऐप कंटेनर में एक सिबलिंग तत्व के रूप में सेट कर रही है, और जब तक कंटेनर आसन्न सिबलिंग कॉम्बीनेटर ( +
) का उपयोग करके खाली नहीं होता है
class App extends React.Component {
state = {
loading: true
};
componentDidMount() {
// this simulates an async action, after which the component will render the content
demoAsyncCall().then(() => this.setState({ loading: false }));
}
render() {
const { loading } = this.state;
if(loading) { // if your component doesn't have to wait for async data, remove this block
return null; // render null when app is not ready
}
return (
<div>I'm the app</div>
);
}
}
function demoAsyncCall() {
return new Promise((resolve) => setTimeout(() => resolve(), 2500));
}
ReactDOM.render(
<App />,
document.getElementById('app')
);
#app:not(:empty) + .sk-cube-grid {
display: none;
}
.sk-cube-grid {
width: 40px;
height: 40px;
margin: 100px auto;
}
.sk-cube-grid .sk-cube {
width: 33%;
height: 33%;
background-color: #333;
float: left;
animation: sk-cubeGridScaleDelay 1.3s infinite ease-in-out;
}
.sk-cube-grid .sk-cube1 {
animation-delay: 0.2s;
}
.sk-cube-grid .sk-cube2 {
animation-delay: 0.3s;
}
.sk-cube-grid .sk-cube3 {
animation-delay: 0.4s;
}
.sk-cube-grid .sk-cube4 {
animation-delay: 0.1s;
}
.sk-cube-grid .sk-cube5 {
animation-delay: 0.2s;
}
.sk-cube-grid .sk-cube6 {
animation-delay: 0.3s;
}
.sk-cube-grid .sk-cube7 {
animation-delay: 0s;
}
.sk-cube-grid .sk-cube8 {
animation-delay: 0.1s;
}
.sk-cube-grid .sk-cube9 {
animation-delay: 0.2s;
}
@keyframes sk-cubeGridScaleDelay {
0%,
70%,
100% {
transform: scale3D(1, 1, 1);
}
35% {
transform: scale3D(0, 0, 1);
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.4.1/react.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.4.1/react-dom.js"></script>
<div id="app"></div>
<!-- add class loader to container -->
<div class="sk-cube-grid">
<div class="sk-cube sk-cube1"></div>
<div class="sk-cube sk-cube2"></div>
<div class="sk-cube sk-cube3"></div>
<div class="sk-cube sk-cube4"></div>
<div class="sk-cube sk-cube5"></div>
<div class="sk-cube sk-cube6"></div>
<div class="sk-cube sk-cube7"></div>
<div class="sk-cube sk-cube8"></div>
<div class="sk-cube sk-cube9"></div>
</div>
समाधान 2 - पास स्पिनर "हैंडलर" को सहारा के रूप में
स्पिनरों के प्रदर्शन की स्थिति पर अधिक बारीक नियंत्रण रखने के लिए, दो फ़ंक्शन बनाएं showSpinner
और hideSpinner
, उन्हें प्रॉपर के माध्यम से रूट कंटेनर में पास करें। फ़ंक्शंस डोम को हेरफेर कर सकते हैं, या स्पिनर को नियंत्रित करने के लिए जो भी आवश्यक हो, कर सकते हैं। इस तरह, रिएक्ट को "बाहरी दुनिया" के बारे में पता नहीं है, न ही सीधे डोम को नियंत्रित करने की आवश्यकता है। आप परीक्षण के लिए कार्यों को आसानी से बदल सकते हैं, या यदि आपको तर्क को बदलने की आवश्यकता है, और आप उन्हें रिएक्ट ट्री में अन्य घटकों को पास कर सकते हैं।
उदाहरण 1
const loader = document.querySelector('.loader');
// if you want to show the loader when React loads data again
const showLoader = () => loader.classList.remove('loader--hide');
const hideLoader = () => loader.classList.add('loader--hide');
class App extends React.Component {
componentDidMount() {
this.props.hideLoader();
}
render() {
return (
<div>I'm the app</div>
);
}
}
// the setTimeout simulates the time it takes react to load, and is not part of the solution
setTimeout(() =>
// the show/hide functions are passed as props
ReactDOM.render(
<App
hideLoader={hideLoader}
showLoader={showLoader}
/>,
document.getElementById('app')
)
, 1000);
.loader {
position: absolute;
top: calc(50% - 4em);
left: calc(50% - 4em);
width: 6em;
height: 6em;
border: 1.1em solid rgba(0, 0, 0, 0.2);
border-left: 1.1em solid #000000;
border-radius: 50%;
animation: load8 1.1s infinite linear;
transition: opacity 0.3s;
}
.loader--hide {
opacity: 0;
}
@keyframes load8 {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.4.1/react.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.4.1/react-dom.js"></script>
<div id="app"></div>
<div class="loader"></div>
उदाहरण 2 - हुक
यह उदाहरण useEffect
घटक माउंट के बाद स्पिनर को छिपाने के लिए हुक का उपयोग करता है ।
const { useEffect } = React;
const loader = document.querySelector('.loader');
// if you want to show the loader when React loads data again
const showLoader = () => loader.classList.remove('loader--hide');
const hideLoader = () => loader.classList.add('loader--hide');
const App = ({ hideLoader }) => {
useEffect(hideLoader, []);
return (
<div>I'm the app</div>
);
}
// the setTimeout simulates the time it takes react to load, and is not part of the solution
setTimeout(() =>
// the show/hide functions are passed as props
ReactDOM.render(
<App
hideLoader={hideLoader}
showLoader={showLoader}
/>,
document.getElementById('app')
)
, 1000);
.loader {
position: absolute;
top: calc(50% - 4em);
left: calc(50% - 4em);
width: 6em;
height: 6em;
border: 1.1em solid rgba(0, 0, 0, 0.2);
border-left: 1.1em solid #000000;
border-radius: 50%;
animation: load8 1.1s infinite linear;
transition: opacity 0.3s;
}
.loader--hide {
opacity: 0;
}
@keyframes load8 {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="app"></div>
<div class="loader"></div>