usage of useEffect blanks out page - javascript

Pretty much the title, when I add
useEffect(() => {
const fetchData = async () => {
const result = await fetch('http://localhost.com/ping');
console.log(result)
};
fetchData();
}, []);
to my component, the page renders properly and then immediately blanks out. Not sure what I did wrong since it's literally the same in the React Documentation.
Full component:
import React from 'react';
import { useEffect } from 'react';
const Test = () => {
useEffect(() => {
const fetchData = async () => {
const result = await fetch('http://localhost.com/ping');
console.log(result)
};
fetchData();
}, []);
return (
<>
<h1>Test</h1>
</>
);
};
export default Test;
App
import { hot } from 'react-hot-loader/root';
import React from 'react';
import Navigation from './components/Navigation/Navigation.jsx';
const App = () => {
return (
<>
<div>Stuff</div>
<Navigation></Navigation>
</>
);
};
export default hot(App);
Navigation
/* eslint-disable react/display-name */
import { BrowserRouter as Router, Route, Link, Switch } from 'react-router-dom';
import React from 'react';
import Home from './Home';
import Login from './Login';
import Logout from './Logout';
import Faq from './Faq';
import Dashboard from './Dashboard';
import Test from './Test';
const Navigation = () => {
const isLoggedIn = false;
return (
<>
<Router>
<div>
<ul>
<li>
<Link to='/'>Home</Link>
</li>
<li>
{isLoggedIn ? (
<Link to='/auth/logout'>Logout</Link>
) : (
<Link to='/auth/login'>Login</Link>
)}
</li>
<li>
<Link to='/auth/dashboard'>Dashboard</Link>
</li>
<li>
<Link to='/faq'>FAQ</Link>
</li>
<li>
<Link to='/test'>Test</Link>
</li>
</ul>
</div>
<Switch>
<Route exact path='/'>
<Home />
</Route>
<Route exact path='/auth/login'>
<Login />
</Route>
<Route path='/auth/logout'>
<Logout />
</Route>
<Route path='/auth/dashboard'>
<Dashboard />
</Route>
<Route path='/faq'>
<Faq />
</Route>
<Route path='/test'>
<Test />
</Route>
</Switch>
</Router>
</>
);
};
export default Navigation;
I have to write some stuff here because stack overflow decided that i am not allowed to post the code that people asked for ...

Try with
useEffect(() => {
const fetchData = async () => {
try {
const result = await fetch('http://localhost.com/ping');
console.log(result)
} catch (e){
console.log(e)
}
};
fetchData();
});
Instead of
useEffect(() => {
const fetchData = async () => {
const result = await fetch('http://localhost.com/ping');
console.log(result)
};
fetchData();
}, []);

You could wrap the fetch call in try/catch block to run your code smoothly.
And use one react import instead of two separate.
import React, {useEffect} from 'react';
const Test = () => {
useEffect(() => {
const fetchData = async () => {
try{
const result = await fetch('http://localhost/ping');
console.log(result)
} catch(error) {
console.log(error.message);
}
};
fetchData();
}, []);
return (
<>
<h1>Test</h1>
</>
);
};
export default Test;

After poking around a bit I finally got an error message : "Test.jsx:26 Uncaught ReferenceError: regeneratorRuntime is not defined"
To fix that install regenerator-runtime and require it globally. Read the readme of regenerator-runtime if you are unsure on how to do that.

Related

React-JS Single post visit is not working | No routes matched location "/posts/1"

I wanted to make a single blog page of a blog website to read but it's not working
I want someone help me to solve this error.
App.js
import Demo from "./components/Pages/Demo/Demo";
import DemoPost from "./components/Pages/Demo/Post";
function App() {
return (
<div>
<Routes>
<Route path='/posts' exact element={<Demo />} />
<Route path='/demo/:pid' element={<DemoPost />} />
</Routes>
</div>
);
}
export default App;
Posts.js
import React, { useState, useEffect } from 'react';
import { Link } from 'react-router-dom';
function Demo() {
const [posts, setPosts] = useState([]);
useEffect(() => {
fetch('https://jsonplaceholder.typicode.com/posts')
.then(response => response.json())
.then(json => setPosts(json))
}, []);
return (
<div className="posts">
<div className="grid">
{posts.map(post => (
<div key={post.id}>
<Link to={`/posts/${post.id}`}>
<h2>{post.title}</h2>
<p>{post.body}</p>
</Link>
</div>
))}
</div>
</div>
)
}
export default Demo
Post.js
import React, { useState, useEffect } from 'react';
import { useParams } from 'react-router-dom';
function Post({ match }) {
const [post, setPost] = useState([]);
useEffect(() => {
fetch(`https://jsonplaceholder.typicode.com/posts${match.params.pid}`)
.then(response => response.json())
.then(json => setPost(json))
console.log(match, 'why not show match');
}, []);
return (
<div className="posts">
<div className="post-container">
<h1>{post.title}</h1>
<p>{post.body}</p>
</div>
</div>
)
}
export default Post
For the link <Link to={`/posts/${post.id}`}> you need to render a route path that matches, e.g. path="/posts/:pid".
<Routes>
<Route path='/posts' exact element={<Demo />} />
<Route path='/posts/:pid' element={<DemoPost />} />
</Routes>
react-router-dom#6 Route components also no longer pass route props to the routed component. The element component should use the useParams hook to access the route path params.
import React, { useState, useEffect } from 'react';
import { useParams } from 'react-router-dom';
function Post() {
const { pid } = useParams();
const [post, setPost] = useState();
useEffect(() => {
fetch(`https://jsonplaceholder.typicode.com/posts/${pid}`)
.then(response => response.json())
.then(json => setPost(json));
}, [pid]); // <-- pid is effect dependency
if (!post) {
return null; // <-- or loading indicator/spinner/etc
}
return (
<div className="posts">
<div className="post-container">
<h1>{post.title}</h1>
<p>{post.body}</p>
</div>
</div>
);
}

react-router does not navigate to desired the route after an async operation

I was working on a project when it turned out that when I dispatched an action and tried to navigate to the /home route after making an async call to my api and using the await keyword to wait for my response , it was not functioning.
I reproduce the problem in a simple react app codesandbox link
The issue with the following code is that it does not navigate to the home route when isLogged is true.
app.js
import "./styles.css";
import { useSelector } from "react-redux";
import {
BrowserRouter as Router,
Routes,
Route,
Navigate
} from "react-router-dom";
import Home from "./component/Home";
import Login from "./component/Login";
export default function App() {
const { isLogged } = useSelector((state) => state.auth);
console.log("rendered");
return (
<div className="App">
<Router>
<Routes>
<Route path="/" element={<Login />} />
<Route path="/home" element={isLogged ? <Home /> : <Login />} />
<Route path="*" element={<Navigate to="/" />} />
</Routes>
</Router>
</div>
);
}
Login.jsx
import { useState } from "react";
import Forms from "./Forms";
const Login = () => {
const [openform, setOpenForm] = useState(false);
return (
<div className="login">
{openform && <Forms />}
{!openform && (
<button onClick={() => setOpenForm(!openform)}>
click to open Form
</button>
)}
</div>
);
};
export default Login;
Forms.jsx
import { useDispatch } from "react-redux";
import { useNavigate } from "react-router-dom";
import { setIsLogged } from "../store/authSlice";
const Forms = () => {
const dispatch = useDispatch();
const navigate = useNavigate();
var goToHome = () => {
dispatch(setIsLogged(true));
navigate("/home");
};
const submit = () => {
setTimeout(() => {
console.log("finished");
goToHome();//It works if I call the goToHome method straight without using the timeout.
}, 2000);
};
return (
<form action="">
<input type="text" placeholder="enter your name" />
<button onClick={submit}>click to login</button>
</form>
);
};
export default Forms;
The code is not preventing the default form action from occurring, resulting in the page reloading and the entire React app remounting. Consume the onSubmit event object and call preventDefault on it.
Example:
const Forms = () => {
const dispatch = useDispatch();
const navigate = useNavigate();
const goToHome = () => {
dispatch(setIsLogged(true));
navigate("/home");
};
const submit = (e) => { // <-- consume onSubmit event object
e.preventDefault(); // <-- prevent default form action
setTimeout(() => {
goToHome();
}, 2000);
};
return (
<form action="">
<input type="text" placeholder="enter your name" />
<button onClick={submit}>click to login</button>
</form>
);
};

BrowserRouter not loading pages [duplicate]

This question already has an answer here:
Why I receive blank page? React
(1 answer)
Closed 11 months ago.
I've used BrowserRouter here, and wrapped the within a tag.
But the problem is, the ShowTodoList page is not rendering.
Is this syntactically correct?
App.js file
import {BrowserRouter, Route, Routes} from 'react-router-dom';
import React, { lazy } from 'react';
import "./App.scss";
const ShowTodoList = lazy(() => import("./components/showTodoList"));
const CreateTodo = lazy(() => import("./components/createTodo"));
function App() {
return (
<div className="app-contents">
TODO - LIST
<BrowserRouter>
<Routes>
<Route path="/" component={ShowTodoList} />
</Routes>
</BrowserRouter>
</div>
);
}
export default App;
ShowTodoList.jsx
import { useState, useEffect } from "react";
import axios from "axios";
import { Link } from "react-router-dom";
import { UpdateTodo } from "./updateTodo";
function TodoCard({ data, handleEdit, handleDelete }) {
const { _id, title, description } = data;
return (
<li key={_id}>
<div className="title-description">
<h3>{title}</h3>
<p>{description}</p>
</div>
<div className="button-container">
<button className="button" name={_id} onClick={handleEdit}>
edit
</button>
<button className="button" name={_id} onClick={handleDelete}>
delete
</button>
</div>
</li>
);
}
export function ShowTodoList() {
const [todo, setTodo] = useState([]);
const [open, setOpen] = useState(false);
const [id, setId] = useState("");
const [update, setUpdate] = useState(false);
useEffect(
function () {
axios
.get("http://localhost:8000/api/todo")
.then((res) => {
console.log(res.data);
setTodo(res.data);
})
.catch((err) => {
console.log(err.message);
});
},
[update]
);
function handleEdit(e) {
setId(e.target.name);
setOpen(true);
}
function handleUpdate() {
console.log("update:", update, !update);
setUpdate(!update);
}
function handleDelete(e) {
axios.delete(`http://localhost:8000/api/todo/${e.target.name}`);
setTodo((data) => {
return data.filter((todo) => todo._id !== e.target.name);
});
}
function handleClose() {
setId("");
setOpen(false);
}
return (
<section className="container">
<Link to="/create-todo" className="button-new">
<button className="button">New</button>
</Link>
<section className="contents">
<h1>TODO</h1>
<ul className="list-container">
{todo.map((data) => (
<TodoCard
data={data}
handleEdit={handleEdit}
handleDelete={handleDelete}
/>
))}
</ul>
</section>
{open ? (
<section className="update-container">
<div className="update-contents">
<p onClick={handleClose} className="close">
×
</p>
<UpdateTodo
_id={id}
handleClose={handleClose}
handleUpdate={handleUpdate}
/>
</div>
</section>
) : (
""
)}
</section>
);
}
I'm getting a blank page as below:enter image description here
Could anybody please check the codes and point out where I'm going wrong?
If you are using react-router version 6, we don't have component props in this version, and you should use element instead of it.
import { BrowserRouter, Route, Routes } from "react-router-dom";
import React, { lazy, Suspense } from "react";
const ShowTodoList = lazy(() => import("./components/showTodoList"));
const CreateTodo = lazy(() => import("./components/createTodo"));
function App() {
return (
<div className="app-contents">
TODO - LIST
<Suspense fallback={<div>Loading...</div>}>
<BrowserRouter>
<Routes>
<Route path="/" element={<ShowTodoList />} />
</Routes>
</BrowserRouter>
</Suspense>
</div>
);
}
export default App;

How to transition from one page to another in react app

i am trying create a transition screen from one page to the other
function MainPage(){
return (
<div>
{pagestate.navigating == "true" ? (
<FadeIn>
<div className="d-flex justify-content-center align-items-center">
<h1>signing you in ....</h1>
<Link to="/" color="black" >sign in</Link>
{pagestate.loading =="false" ? (
<Lottie options={defaultOptions} height={120} width={120} />
) : (
<Lottie options={defaultOptions2} height={220} width={120} />
)}
</div>
</FadeIn>
) : (
<div>
<h1>hello world</h1>
<Link to="/" color="black" >sign in</Link>
</div>
)}
The code works fine but I want it to navigate to /page2 when pagestate.loading = "false". I was able to achieve the page navigation with using
const history = useHistory()
then call navigation like
history.push('/page2')
I tried couple of method but could not get it work inside the transition logic.
How can I incorporate to the navigation into a new page after loading state has been changed to false in the transition logic above?
Encountered that a couple of days ago, i found a solution to it but it’s kinda weird,i’ve done it using redux, i’ve made a Link Component Called LinkWithAnimation,created a reducer as RouteReducer which will store current transition state, 2 states:
First one is For Transitioning In.
Second one is For Transitioning Out.
Wrapped my application with a div and passed the Transition that’s stored in redux, everytime LinkWithAnimation Is clicked This Is What Happens:
Dispatch An Action For Transitioning In
Wait(Delay) Till the Transition Has Finished(Depending On The Duration Of It)
Dispatch An Action for Transitioning Out.
And then push the new path using History API.
Note: Make Use Of Redux Thunk.
ActionTypes.js
export const ActionsType = {
...otherActions,
ANIMATION_IN: "animation-in",
ANIMATION_OUT: "animation-out",
};
ActionsCreator.js
import { ActionsType } from "./ActionsType.js";
import { history } from "../index.js";
export const ActionsCreator = {
...otherActionCreators,
userLogout: () => ({ type: ActionsType.LOGOUT }),
animateIn: () => ({ type: ActionsType.ANIMATION_IN }),
animateOut: () => ({ type: ActionsType.ANIMATION_OUT }),
pageTransition: (duration, path) => {
return async (dispatch) => {
const delay = async () => {
return new Promise((resolve) => setTimeout(resolve, duration));
};
dispatch(ActionsCreator.animateOut());
await delay();
dispatch(ActionsCreator.animateIn());
history.push(path);
};
},
};
index.js
import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
import { Router } from "react-router-dom";
import { createBrowserHistory } from "history";
export const history = createBrowserHistory();
ReactDOM.render(
<Router history={history}>
<React.StrictMode>
<App />
</React.StrictMode>
</Router>,
document.getElementById("root")
);
LinkWithAnimation.js
import React, { useRef, useEffect } from "react";
import { Link } from "react-router-dom";
import { ActionsCreator } from "../actions/ActionsCreator.js";
import { connect } from "react-redux";
const LinkWithAnimation = ({
className,
additionalFunction,
PageTransitioning,
to,
children,
style,
component,
ReactTo,
disabled,
}) => {
const LinkRef = useRef();
// This Effect To Handle Page Transition Once The User Is Signed In
useEffect(() => {
if (ReactTo === true) {
LinkRef.current.click();
}
}, [ReactTo]);
const componentProp =
component !== undefined
? {
component: component,
}
: {};
return (
<>
<Link
onClick={async () => {
if (disabled) return;
PageTransitioning(230, to);
if (additionalFunction !== undefined) {
additionalFunction();
}
}}
ref={LinkRef}
className={className}
style={{ ...style }}
{...componentProp}
>
{children}
</Link>
</>
);
};
const mapDispatchToProps = (dispatch) => ({
PageTransitioning: (duration, path) => {
dispatch(ActionsCreator.pageTransition(duration, path));
},
});
export default connect(null, mapDispatchToProps)(LinkWithAnimation);
Main.js
import React, { Fragment } from "react";
import { Switch, Route } from "react-router-dom";
import { connect } from "react-redux";
import Homepage from "./Homepage/Homepage.js";
import Signup from "./Signup/Signup.js";
import UserInterface from "./UserInterface/UserInterface.js";
import { SignIn } from "./SignIn/SignIn.js";
import { useRouteTransitionScroll } from "../hooks/useRouteTransitionScroll.js";
const Main = ({ keyframe }) => {
useRouteTransitionScroll({
from: "/signup",
to: "/home",
scroll_y: 650,
});
return (
<Switch component={Fragment}>
<div
style={{
animationName: keyframe,
animationDuration: "250ms",
animationTimingFunction: "linear",
}}
>
<Route path="/mainpage">
<UserInterface />
</Route>
<Route path="/home">
<Homepage />
</Route>
<Route path="/signin">
<SignIn />
</Route>
<Route path="/signup">
<Signup />
</Route>
</div>
</Switch>
);
};
const mapStateToProps = (state) => ({
keyframe: state.Route.animationName,
});
export default connect(mapStateToProps)(Main);

React hook Redirect on component mount

I am trying to manage session after successful login while redirecting to some page on form submit.
I would do this usually, in a class component:
componentDidMount() {
if (context.token) {
return <Redirect to="/" />
}
}
But I want to use React hooks, therefore; the following code is not redirecting anywhere:
import React, { useEffect } from "react";
import ReactDOM from "react-dom";
import { BrowserRouter, Switch, Route, Redirect, Link } from "react-router-dom";
es6
const HomePage = props => (
<div>
<h1>Home</h1>
</div>
);
const AboutUsPage = props => {
useEffect(() => {
redirectTo();
}, []);
return (
<div>
<h1>About us</h1>
</div>
);
};
function redirectTo() {
return <Redirect to="/" />;
}
function App() {
return (
<div className="App">
<BrowserRouter>
<nav>
<Link to="/">Home</Link>
<Link to="/us">About us</Link>
</nav>
<Switch>
<Route exact path="/" component={HomePage} />
<Route exact path="/us" component={AboutUsPage} />
</Switch>
</BrowserRouter>
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
Working sandbox: https://codesandbox.io/s/blue-river-6dvyv?fontsize=14
I have read that if the hook useEffect() returns a function it will only work when the component unmounts. But it should redirect when the component is being mounted.
Any suggestions? Thanks in advance.
You could set redirect variable on the state and based on it redirect in render:
const AboutUsPage = props => {
const [redirect, setRedirect] = useState(false);
useEffect(() => {
setRedirect(true); // Probably need to set redirect based on some condition
}, []);
if (redirect) return redirectTo();
return (
<div>
<h1>About us</h1>
</div>
);
};
You could have it so that the component selectively renders the page based on whether or not the page is given a token.
const AboutUsPage = ({token}) => (
token ? (
<Redirect to="/" />
) : (
<div>
<h1>About us</h1>
</div>
)
);
However, if you would still like to use context when implementing this with React Hooks you can read up on how to use context with hooks in this article. It shows you how you can incorporate context into React with only a few lines of code.
import React, {createContext, useContext, useReducer} from 'react';
export const StateContext = createContext();
export const StateProvider = ({reducer, initialState, children}) =>(
<StateContext.Provider value={useReducer(reducer, initialState)}>
{children}
</StateContext.Provider>
);
export const useStateValue = () => useContext(StateContext);
Done with hooks and context, your AboutUsPage component would resemble something like this.
import { useStateValue } from './state';
const AboutUsPage = () => {
const [{token}, dispatch] = useStateValue();
return token ? (
<Redirect to="/" />
) : (
<div>
<h1>About us</h1>
</div>
);
};
import {Redirect, Switch} from "react-router-dom";
and inside Switch....
<Switch>
<Redirect exact from="/" to="/home" />
</Switch>
This solved my issue.

Categories