Amaç
Html sayfası oluşturulduğunda, hemen bir döndürücü görüntüleyin (React yüklenirken) ve React hazır olduktan sonra gizleyin.
Değer değiştirici saf HTML / CSS'de (React etki alanının dışında) işlendiğinden, React gösterme / gizleme işlemini doğrudan kontrol etmemeli ve uygulama React'e şeffaf olmalıdır.
Çözüm 1 - The: Boş Sahte Sınıf
Bir DOM kabına tepki <div id="app"></div>
verdiğinizden - , bu kaba bir spinner ekleyebilirsiniz ve reaksiyonun yüklenmesi ve görüntülenmesi durumunda, spinner kaybolacaktır.
Tepkime köküne bir DOM öğesi (örneğin bir div) ekleyemezsiniz, çünkü React kapsayıcı içeriği ReactDOM.render()
çağrılır değiştirilmez. Oluştursanız bile null
, içerik yine de bir yorumla değiştirilir - <!-- react-empty: 1 -->
. Bu, ana bileşen monte edilirken yükleyiciyi görüntülemek istiyorsanız, veriler yüklenir, ancak gerçekte hiçbir şey oluşturulmazsa, kabın içine yerleştirilmiş bir yükleyici işaretlemesi ( <div id="app"><div class="loader"></div></div>
örneğin) çalışmaz.
Çözüm, spinner sınıfını reaksiyon kabına eklemek ve :empty
sözde sınıfı kullanmaktır . Kap içine hiçbir şey girmediği sürece, döndürücü görünür olacaktır (yorumlar sayılmaz). Tepki yorumdan başka bir şey yapar oluşturmaz, yükleyici kaybolacaktır.
örnek 1
Örnekte, null
hazır olana kadar oluşturulan bir bileşeni görebilirsiniz . Kap da yükleyicidir - <div id="app" class="app"></div>
ve yükleyicinin sınıfı yalnızca şu durumda çalışır :empty
(koddaki yorumlara bakın):
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 -->
ÖRNEK 2
Bir :empty
seçiciyi göstermek / gizlemek için sözde sınıfı kullanmanın bir varyasyonu , çeviriciyi uygulama kapsayıcısına bir kardeş öğe olarak ayarlamak ve bitişik kardeş birleştiricisi ( +
) kullanılarak kap boş olduğu sürece göstermektir :
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>
Çözüm 2 - Dönen "işleyicileri" sahne olarak geçirin
, İplikçiler görüntü durumu üzerinde daha fazla ince taneli kontrol iki işlev oluşturmak showSpinner
ve hideSpinner
, ve sahne ile kök kaba bunları geçmektedir. İşlevler DOM'yi değiştirebilir veya döndürücüyü kontrol etmek için gereken her şeyi yapabilir. Bu şekilde React, "dış dünya" nın farkında değildir ve DOM'u doğrudan kontrol etmesi gerekmez. Test için fonksiyonları kolayca değiştirebilir veya mantığı değiştirmeniz gerekirse ve bunları React ağacındaki diğer bileşenlere aktarabilirsiniz.
örnek 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>
Örnek 2 - kancalar
Bu örnek useEffect
, bileşen takıldıktan sonra döndürücüyü gizlemek için kancayı kullanır .
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>