render a component after some time with setTimeout ( ReactJs) - javascript

I want to render one component inside my App.Js after some time pass with setTimeout, there is any way to do that?
when I try, nothing happens...
my code:
function App() {
return (
<Router>
<GlobalStyle />
<SearchProvider>
<Header />
<Switch>
<Route exact path="/">
{setTimeout(() => {
return;
<>
<InitialLoad />
<Home />
</>;
}, 1200)}
</Route>
<Route exact path="/series">
<Series />
</Route>
<Route exact path="/movies">
<MoviesPage />
</Route>
<Route exact path="/popular">
<PopularPage />
</Route>
<Route exact path="/resultado-de-busca">
<SearchPage />
</Route>
</Switch>
</SearchProvider>
</Router>
);
}
want my InitialLoad and Home Components show after 1200 time, but nothing happens, how I fix it, please?

If you want to do that in the Route:
import { useState } from "react";
function App() {
const [isDisplayed, setIsDisplayed] = useState(false);
useEffect(() => {
setInterval(() => {
setIsDisplayed(true);
}, 1200);
}, []);
return (
<Router>
<GlobalStyle />
<SearchProvider>
<Header />
<Switch>
<Route exact path="/">
{isDisplayed &&
<>
<InitialLoad />
<Home />
</>;
}
</Route>
//the rest of your component

Route is to choose what component to render depends on your path (URL).
if you want to refresh your component, you need to change state value, or props value from parent.
try something like this:
import { useState } from "react";
import "./styles.css";
export default function App() {
const [isHide, setIsHide] = useState(true);
setTimeout(() => setIsHide(false), 5000);
return (
<div className="App">
<h1>testing delay render</h1>
{!isHide ? <div>show after 5 seconds</div> : null}
</div>
);
}

Your best bet would probably be to use hooks in React. Essentially creating your components<InitialLoad /> <Home /> as usual in App.js but set display:none at the start, and then have your setTimeout() change the state and display your components.
This article may help
https://reactgo.com/settimeout-in-react-hooks/

Related

Trigger a rerender of parent component when a child component is rendered

I am using the following material-ui theme Paperbase and within the Header.js component, I have the following useEffect hook:
const [temperature, setTemperature] = useState([]);
const getTemperature= async () => {
try {
const response = await fetch('/get-temperature')
const tempData = await response.json();
setTemperature(tempData);
} catch (err) {
console.error(err.message);
}
};
useEffect(() => {
getTemperature();
}, []);
The main purpose of this, is to display the current temperature as info, within the header component, which gets displayed at first page load/render.
Now within my App.js below, I have the following return setup where the above Header component is called.
return (
<Router>
<UserProvider myinfo={myinfo}>
<Switch>
<Route path="/">
<ThemeProvider theme={theme}>
<div className={classes.root}>
<CssBaseline />
<nav className={classes.drawer}>
<Hidden xsDown implementation="css">
<Navigator />
</Hidden>
</nav>
<div className={classes.app}>
<Header
onDrawerToggle={handleDrawerToggle}
/>
<main className={classes.main}>
<Switch>
<Route exact path="/new-user"
render={(props) => <Content key={props.location.key} />}
/>
<Route exact path="/view-results"
render={(props) => <ViewResults key={props.location.key} />}
/>
</Switch>
</main>
</div>
</div>
</ThemeProvider>
</Route>
</Switch>
</UserProvider>
</Router>
);
My question is, how can I trigger a rerender of Header (parent) whenever the user routes to either /new-user or /view-results which in turn calls either Content.js or ViewResults.js, inorder to make the useEffect in Header.js refresh the data, from the REST api fetch and display the latest temperature in the header again?
Ideally anytime Content.js or ViewResults.js is rendered, ensure that Header.js getTemperature() is called.
Any help would be much appreciated.
Your current code is pretty close to a multi layout system. As being a component child of Route, you can access the current location via useLocation() or even the native window.location.pathname.
This is my example of multi layout React app. You can try to use it to adapt to your code.
The MainLayout use a fallback route when no path is specified. It also contains a Header and include a page
const Dispatcher = () => {
const history = useHistory();
history.push('/home');
return null;
};
const App = () => (
<BrowserRouter>
<Switch>
<Route
component={Dispatcher}
exact
path="/"
/>
<Route
exact
path="/login/:path?"
>
<LoginLayout>
<Switch>
<Route
component={LoginPage}
path="/login"
/>
</Switch>
</LoginLayout>
</Route>
<Route>
<MainLayout>
<Switch>
<Route
component={HomePage}
path="/home"
/>
</Switch>
</MainLayout>
</Route>
</Switch>
</BrowserRouter>
);
And here is the code for MainLayout
const MainLayout = ({ children }) => (
<Container
disableGutters
maxWidth={false}
>
<Header location={props.location} />
<Container
component="main"
maxWidth={false}
sx={styles.main}
>
{children}
</Container>
<Footer />
</Container>
);
Now that Header can be anything. You need to put a capture in this component
import { useLocation } from 'react-router-dom'
cont Header = (props) => {
const { pathname } = useLocation();
//alternatively you can access props.location
useEffect(() => {
if (pathname === '/new-user') {
getTemperature();
}
}, [pathname]);
};
Note that Header is not a direct descendant of Route therefore it cannot access the location directly via props. You need to transfer in chain
Route -> MainLayout -> Header
Or better use useLocation

React - can a component be styled depending on what other component is rendered?

I have a Search component, when the homepage component is rendered I'd like the Search component to be rendered at the bottom of the page. When any other page component is rendered I'd like the Search component to be at the top of the page.
Currently what I have my app.js as:
const App = () => {
return (
<BrowserRouter>
<Switch>
<Route path='/' component={Home} />
<Route path='/about' component={About} />
<Route path='/work' component={Work} />
<Route path='/contact' component={Contact} />
</Switch>
</BrowserRouter>
)
}
and inside a page component:
const Contact = () => {
return (
<div>
<Search />
Contact
</div>
)
}
Obviously this way means I have to add the Search component to every component and choose whether I place it at the top or bottom.
My question is this, can I place it on the app.js like so:
const App = () => {
return (
<BrowserRouter>
<Search />
<Switch>
<Route path='/' component={Home} />
<Route path='/about' component={About} />
<Route path='/work' component={Work} />
<Route path='/contact' component={Contact} />
</Switch>
</BrowserRouter>
)
}
And then depending on which page component is being rendered, style the Search component so it either appears at the top or bottom of the page.
Thanks
I would add a className prop to the Search component and add some if statement.
For example:
<Search className={location === '/' ? 'top' : 'bottom'} />
With the useLocation() hook provided by React Router, you can determine what page you're on.
const Contact () => {
const location = useLocation();
const styles = location === "something" ? {...topStyles} : {...downStyles};
return (
<div>
<Search style={styles} />
Contact
</div>
)
}

Why you can't render from 2 JSX element?

My goal is to render <Route /> with array.map method. Right now, I am trying to pass the return value using react hook, but the problem is localhost:3000/login return <div>Login</div> while localhost:3000/dashboard return nothing.
My expected result is when I visit localhost:3000/dashboard the JSX.element return <div>Dashboard</div>
App.js
import React from "react";
import { BrowserRouter as Router, Switch, Route } from "react-router-dom";
const PublicRouteComponents = () => {
return <Route exact path="/login" render={() => <div>Login</div>} />
};
const PrivateRouteComponents = () => {
return <Route exact path="/dashboard" render={() => <div>Dashboard</div>} />
};
function App() {
return (
<Router>
<Switch>
{/* <Route exact path="/login" render={() => <div>Login</div>} />
<Route exact path="/dashboard" render={() => <div>Dashboard</div>} /> */}
<PublicRouteComponents />
<PrivateRouteComponents />
</Switch>
</Router>
);
}
export default App;
edit:
the current solution is to give up the react hook and went straight to JSX.element
function App() {
const PublicRouteComponents = PublicRoutes.map(
({restricted, component, path}, key) => <PublicRoute restricted={restricted} component={component} exact path={path} key={key} />
)
const PrivateRouteComponents = PrivateRoutes.map(
({component, path}, key) => <PrivateRoute component={component} exact path={path} key={key} />
)
return (
<Router>
<Switch>
{PublicRouteComponents}
{PrivateRouteComponents}
</Switch>
</Router>
);
}
But, my instructor told me, if you gave an expression instead of class, when the component inside {PublicRouteComponents} changes, the app will got re-rendered. Instead if you use <PublicRouteComponents />, when the class change, only <PublicRouteComponents /> will be re-rendered.
I wish to achieve that.
After playing around a bit, I found the underlying issue in your first code sample.
Basically, React router demands that the route path and the exact props to be set in the children of the Router component.
import React from "react";
import { BrowserRouter as Router, Switch, Route } from "react-router-dom";
const LoginRoute = () => {
return <Route render={() => <div>Login</div>} />;
};
const DashboardRoute = () => {
return <Route render={() => <div>Dashboard</div>} />;
};
export default function App() {
return (
<Router>
<Switch>
<DashboardRoute exact path="/dashboard" />
<LoginRoute exact path="/login" />
</Switch>
</Router>
);
}
If you move the path and exact props to the DashboardRoute and LoginRoute components, then react router is unable to match those routes.
See codesandbox

React router rendering two child components instead of just one

I'm trying to add routes to my application but for some reason there are two components being rendered to the page instead of just one.
My code looks like this (the relevant part):
import React from "react";
import Board from "./Components/Board";
import Navbar from "./Components/Navbar";
import TaskDetail from "./Components/TaskDetail";
import { LanesProvider } from "./Context/lanes.context";
import { TasksProvider } from "./Context/tasks.context";
import { BrowserRouter, Route, Switch } from "react-router-dom";
function App(props) {
const getTask = props => {
return <TaskDetail />;
};
return (
<>
<LanesProvider>
<TasksProvider>
<Navbar />
<Board />
<BrowserRouter>
<Switch>
<Route exact path="/" render={() => <Board />} />
<Route exact path="/board" render={() => <Board />} />
<Route exact path="/board/:taskName" render={() => getTask()} />
</Switch>
</BrowserRouter>
</TasksProvider>
</LanesProvider>
</>
);
}
Now basically when I'm navigating to "localhost/board/test" I would expect to just see the <TaskDetail/> component but instead I get the <Board /> AND <TaskDetail/>.
I didn't expect this to happen because of the exact boolean.
FYI: getTask() is only returning a component right now because I wanted to get the routes to work first before implementing further logic.
So far I could not find a solution to this.
Thank you in advance.
There is a <Board /> component outside your <BrowserRouter>
import React from "react";
import Board from "./Components/Board";
import Navbar from "./Components/Navbar";
import TaskDetail from "./Components/TaskDetail";
import { LanesProvider } from "./Context/lanes.context";
import { TasksProvider } from "./Context/tasks.context";
import { BrowserRouter, Route, Switch } from "react-router-dom";
function App(props) {
const getTask = props => {
return <TaskDetail />;
};
return (
<>
<LanesProvider>
<TasksProvider>
<Navbar />
<Board /> --> Remove this component from here
<BrowserRouter>
<Switch>
<Route exact path="/" render={() => <Board />} />
<Route exact path="/board" render={() => <Board />} />
<Route exact path="/board/:taskName" render={() => getTask()} />
</Switch>
</BrowserRouter>
</TasksProvider>
</LanesProvider>
</>
);
}

Programmatically navigate while using HashRouter

I'm using HashRouter for my routes in a react.js app. I then have a function which does the following:
this.props.history.push('/somePath');
The problem is, ever since I started using HashRouter, the page doesn't push to that path when that function gets called.
I logged this.props.history, and push was there.
How can I programmatically navigate while using HashRouter?
Note: I used withRouter
Here's the code:
import React, { Component } from 'react';
import { HashRouter, Route, Switch, Redirect, withRouter } from 'react-router-dom';
// Other imports
class App extends Component {
navigate = () => {
this.props.history.push('/route1');
console.log(this.props.history);
};
render() {
return (
<div className="App">
<Header />
<HashRouter>
<Switch>
<Route
path="/route1"
exact
render={() => (
<FirstRoute someSetting='setting1'/>
)}
/>
<Route
path="/route2"
exact
render={() => (
<SecondRoute anotherSetting='Really Cool'/>
)}
/>
<Route path="/404" component={NotFound} />
<Route exact path="/" render={() => <HomePage someSettings='Home Page' />} />
<Redirect to="/404" />
</Switch>
</HashRouter>
<BottomBar />
</div>
);
}
}
export default withRouter(App);

Categories

Resources