We all know what a loading icon is, in React, I am wanting to replace that icon with an image/gif I have created. I have used npm i react-loading
as the package, however, as this is my first time with this package, I am unsuccessful in having my images display at all. Im not entirely sure if this is due to a pathing error, or something else.
The intentions of this loader was to display this gif while the DOM is rendering, however, since I created the gifs myself, I love them so much I want to force other people to watch the gif in it's entirety before continuing. I have set a 5 second timeout on it, but not exactly sure if that was the right move. Maybe having a ternary would have been a simpler way to accomplish this.
Below is the Loading component I have set:
import {useState, useEffect} from 'react'
import Loading from 'react-loading'
const loadingGifsList = [
'../loading-images/l1.gif',
'../loading-images/l2.gif',
'../loading-images/l3.gif',
'../loading-images/l4.gif',
'../loading-images/l5.gif',
'../loading-images/l6.gif',
'../loading-images/l7.gif',
'../loading-images/l8.gif',
'../loading-images/l9.gif',
'../loading-images/l10.gif',
'../loading-images/l11.gif',
'../loading-images/l12.gif',
'../loading-images/l13.gif'
]
const LoadingPage = () => {
const [isLoading, setIsLoading] = useState(true)
const loadingGif = loadingGifsList[Math.floor(Math.random() * loadingGifsList.length)]
useEffect(() => {
const timeout = setTimeout(() => {
setIsLoading(false)
}, 5000);
return () => clearTimeout(timeout)
}, [])
if (isLoading) {
return (
<>
<div>
<Loading src={loadingGif} />
</div>
</>
)
}
}
export default LoadingPage
I have an array of gifs, and one will be randomly selected.
Below is my App.js
:
import axios from 'axios'
import { useState, useEffect } from 'react'
import Header from './components/Header.js'
import Add from './components/Add.js'
import Rules from './components/Rules.js'
import Select from './components/SelectGame'
import Player from './components/PlayerSelect.js'
import Board1 from './components/Player1_Board'
import Board2 from './components/Player2_Board'
import 'bootstrap/dist/css/bootstrap.min.css';
// import LoadingPage from './components/Loading.js'
// import css
import IndexCSS from './index.module.css';
import LoadingPage from './components/Loading.js'
const App = () => {
// API data
let [games, setGames] = useState([])
// show/hides Add.js
let [showAdd, setAdd] = useState(false)
// show/hides Rules.js
let [showRules, setRules] = useState(true)
// show/hides SelectGame.js
let [showSelect, setSelect] = useState(false)
// show/hides the PlayerSelect and Player1/Player2 board until choice is made on SelectGame.js
let [currentGameID, setCurrentGameID] = useState('')
// show/hides PlayerSelect.js page
let [playerSelect, setPlayerSelect] = useState(true)
// show/hides Player1_Board.js page
let [showP1, setP1] = useState(false)
// show/hides Player2_Board.js page
let [showP2, setP2] = useState(false)
//show/hides loading images
const [isLoading, setIsLoading] = useState(true)
//=========================================================================
//DELETE GAME
const handleDelete = (event) => {
axios.delete('https://connect4back.herokuapp.com/api/connect4/' event.id).then((response) => {
getGames();
})
}
//=========================================================================
//EDIT GAME
const handleUpdate = (game) => {
axios.put('https://connect4back.herokuapp.com/api/connect4/' game.id, game).then((response) => {
getGames();
})
}
//=========================================================================
//Create new game with players
const handleCreate = (add) => {
axios.post('https://connect4back.herokuapp.com/api/connect4', add).then((response) => {
getGames();
})
}
//=========================================================================
//collect from database
const getGames = () => {
axios.get('https://connect4back.herokuapp.com/api/connect4').then((response) =>
setGames(response.data),
// , (err) =>
// console.log(err)
)
}
//=========================================================================
//useEffect to collect from database
useEffect(() => {
getGames();
}, [])
// ========================================================================
// display page
return (
<>
<div>
<LoadingPage isLoading={isLoading} setIsLoading={setIsLoading} />
</div>
<div className={IndexCSS.appContainer}>
{/* Header of app */}
<Header setAdd={setAdd} setRules={setRules} setSelect={setSelect} setCurrentGameID={setCurrentGameID} setP1={setP1} setP2={setP2}/>
<div key={games.id}>
{/* Show/Hide Rules.js */}
{
showRules === true ? <Rules setRules={setRules}/> : null
}
{/* Show/Hide Add.js */}
{
showAdd === true ? <Add handleCreate={handleCreate} setAdd={setAdd} setSelect={setSelect}/> : null
}
{/* show/hide SelectGame.js */}
{
showSelect === true ? <Select games={games} setSelect={setSelect} setCurrentGameID={setCurrentGameID} setPlayerSelect={setPlayerSelect}/> : null
}
{
}
{/* render game based on game ID selected from SelectGame.js */}
{games.map((game) => {
if (game.id === currentGameID) {
return (
<div key={game.id}>
{/* Have player select P1 or P2, then render page */}
{
playerSelect === true ? <Player game={game} setP1={setP1} setP2={setP2} setSelect={setSelect} setPlayerSelect={setPlayerSelect}/>: null
}
{/* show P1 page if true, else null */}
{
showP1 === true? <Board1 game1={game} handleDelete={handleDelete} handleUpdate={handleUpdate} /> : null
}
{/* show P1 page if true, else null */}
{
showP2 === true? <Board2 game2={game} handleDelete={handleDelete} handleUpdate={handleUpdate} /> : null
}
</div>
)
} else {
return null
}
})}
</div>
</div>
</>
)
}
export default App
What is this currently producing?
So currently, when the page is loading, I have four circles moving left to right, and the most right circle fades out as a "new" circle (far left) fades in. It looks like a loading icon if you ask me. Why is it in the top left corner and not the centre? I have no idea.
Summary
In react, I want to use my gif/img as my loading "icon." I also like this image to be the centre of the screen. Just like most loaders, I would also like this to be the only thing visible while the loading icon is showing, and when it ends, display what the DOM has rendered.
Below is an image of what I see in the top left corner of my screen:
CodePudding user response:
You need to move the isLoading
state outside of the loading component and instead into the App.js component. Then, you should conditionally render only the loading component when the app is loading (basically the code you have in your loading component right now, that should be moved to App.js
). You should then change your loading component to always render the GIF (since its render is controlled by App.js)
CodePudding user response:
Is this the library that you are using? https://github.com/fakiolinho/react-loading/blob/master/lib/react-loading.jsx#L7
As far as I checked, the library does not support any custom loading image.
I would recommend you use the official React Suspense instead and of course you can do any custom loading image. https://17.reactjs.org/docs/concurrent-mode-suspense.html