I have a CRUD todo application where the user logs in if they are not logged in and this is stored locally. Also todo app making CRUD operations via API. But even if the user is logged in, when the page is refreshed, the login screen appears and disappears for a moment. How can I solve this?
const [todoList, setTodoList] = useState([]);
const [newTask, setNewTask] = useState("");
const [todoEditing, setTodoEditing] = useState(null);
const [editingText, setEditingText] = useState("");
const [username, setUsername] = useState("");
const [savedUsername, setSavedUsername] = useState("");
const [theme, setTheme] = useState("light");
const [addLoading, setAddLoading] = useState(false); // when adding a todo loading spinner appears in button
const [todoLoading, setTodoLoading] = useState(null); //when crud operations happen a loading spinner appears in todo cards
const [loading, setLoading] = useState(false); // loading state for crud functions
const [loginLoading, setLoginLoading] = useState(false); // loading screen for app rendering
useEffect(() => {
setLoginLoading(true);
const storageUsername = localStorage.getItem("username");
if (storageUsername) {
setSavedUsername(storageUsername);
}
setLoginLoading(false);
}, []);
<ThemeContext.Provider value={{ theme }} style={{ position: "relative" }}>
{savedUsername ? (
<div className="container">
.... Components
</div> ) : (
<div className="login-container" id={theme}>
{loginLoading ? (
<Loading />
) : (
<Login
handleChange={setUsername}
handleLogin={handleLogin}
value={username}
/>
)}
</div>
)}
</ThemeContext.Provider>
CodePudding user response:
Your effect from useEffect
is only executed after your first render. So your first state for the loginLoading
is false
then true
and then false
again. This should fix it:
const [todoList, setTodoList] = useState([]);
const [newTask, setNewTask] = useState("");
const [todoEditing, setTodoEditing] = useState(null);
const [editingText, setEditingText] = useState("");
const [username, setUsername] = useState("");
const [savedUsername, setSavedUsername] = useState("");
const [theme, setTheme] = useState("light");
const [addLoading, setAddLoading] = useState(false); // when adding a todo loading spinner appears in button
const [todoLoading, setTodoLoading] = useState(null); //when crud operations happen a loading spinner appears in todo cards
const [loading, setLoading] = useState(false); // loading state for crud functions
const [loginLoading, setLoginLoading] = useState(true); // loading screen for app rendering
useEffect(() => {
const storageUsername = localStorage.getItem("username");
if (storageUsername) {
setSavedUsername(storageUsername);
}
setLoginLoading(false);
}, []);
<ThemeContext.Provider value={{ theme }} style={{ position: "relative" }}>
{savedUsername ? (
<div className="container">
.... Components
</div> ) : (
<div className="login-container" id={theme}>
{loginLoading ? (
<Loading />
) : (
<Login
handleChange={setUsername}
handleLogin={handleLogin}
value={username}
/>
)}
</div>
)}
</ThemeContext.Provider>
But, to improve even more, I wouldn't use a loading state for the login because localStorage.getItem("username")
is a synchronous operation that can be performed more elegantly like that:
const [todoList, setTodoList] = useState([]);
const [newTask, setNewTask] = useState("");
const [todoEditing, setTodoEditing] = useState(null);
const [editingText, setEditingText] = useState("");
const [username, setUsername] = useState("");
const [savedUsername, setSavedUsername] = useState(() => localStorage.getItem("username") || "");
const [theme, setTheme] = useState("light");
const [addLoading, setAddLoading] = useState(false); // when adding a todo loading spinner appears in button
const [todoLoading, setTodoLoading] = useState(null); //when crud operations happen a loading spinner appears in todo cards
const [loading, setLoading] = useState(false); // loading state for crud functions
<ThemeContext.Provider value={{ theme }} style={{ position: "relative" }}>
{savedUsername ? (
<div className="container">
.... Components
</div> ) : (
<div className="login-container" id={theme}>
<Login
handleChange={setUsername}
handleLogin={handleLogin}
value={username}
/>
</div>
)}
</ThemeContext.Provider>