I want my "About" Component to stay until the animation of the new Component is done!
Thats my App.js:
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
import {Route, Link} from 'react-router-dom';
import Projects from './components/Projects';
import About from './components/About';
import PageShell from './components/PageShell';
import Header from './components/Header';
class App extends Component {
render() {
return (
<div className="App">
<Header/>
<div className="App-main">
<Route path="/projects" exact component={PageShell(Projects)}/>
<Route path="/" exact component={PageShell(About)}/>
</div>
</div>
);
}
}
export default App;
PageShell.js:
import React from 'react';
import ReactCSSTransitionGroup from 'react-addons-css-transition-group';
const PageShell = Page => {
return props =>
<div className="page">
<ReactCSSTransitionGroup
transitionName={props.match.path === '/projects' ? 'slideIn' : 'slideOut'}
transitionAppearTimeout={1000}
transitionEnterTimeout={1000}
transitionLeaveTimeout={2000}
transitionAppear={true}
>
<Page {...props} />
</ReactCSSTransitionGroup>
</div>;
};
export default PageShell;
When i click on a div in the About-Page, it disappear instantly and the animation for the Project-Page starts. But i want the About-Compinent to stay until Projects slided in. Projects should be above About.
Any ideas?
Related
I'm a newbie in React js and currently i'm building a layout that contains from many components
For example, a home page layout that contains sidebar component, topbar component, footer component and main content component.
When i click on a link in sidebar component, the main content will be changed based on url of link i clicked on and other components will be same on all pages regardless of url.
Here is my code:
MainLayout.js
import React, { Component } from 'react';
import { Route } from 'react-router-dom';
import Sidebar from '../components/Sidebar';
const MainLayout = ({children, ...rest}) => {
return (
<div className="page page-dashboard">
{/* <div className="sidebar"><Sidebar></Sidebar></div> */}
<div className="main">
{children}
</div>
</div>
)
}
const MainLayoutRoute = ({component: Component, ...rest}) => {
return (
<Route {...rest} render={matchProps => (
<MainLayout>
<Component {...matchProps} />
</MainLayout>
)} />
)
};
export default MainLayoutRoute;
MainPage.js
import React, { Component } from 'react';
import { BrowserRouter as Router, Route, Redirect, Switch } from 'react-router-dom';
import Sidebar from './Sidebar';
import Header from './Header';
import Footer from './Footer';
import UsersList from './UsersList';
export default class MainPage extends Component {
render() {
return (
<Router>
<div>
<Header/>
<Sidebar/>
<div className="wrapper">
<Switch>
<Route path={"/users"} component={UsersList} />
</Switch>
</div>
<Footer></Footer>
</div>
</Router>
);
}
}
Sidebar.js
import React, { Component } from 'react';
import { BrowserRouter as Router, Route, Redirect, Switch, Link } from 'react-router-dom';
export default class Sidebar extends Component {
render() {
return (
<div className="sidenav">
<ul>
<li><Link to="/users">Users</Link></li>
<li><Link to="/settings">Setting</Link></li>
</ul>
</div>
);
}
}
UserList.js
import React, { Component } from 'react';
import { BrowserRouter as Router, Route, Redirect, Switch, Link } from 'react-router-dom';
export default class UsersList extends Component {
render() {
return (
<div>
<button><Link to="/newuser">Add new user</Link></button>
</div>
);
}
}
App.js
import React, { Component } from 'react';
import { BrowserRouter as Router, Route, Redirect, Switch } from 'react-router-dom';
import logo from './logo.svg';
import './App.css';
import './css/custom.scss';
/** Layouts **/
import LoginLayoutRoute from "./layouts/LoginLayout";
import MainLayoutRoute from "./layouts/MainLayout";
/** Components **/
import MainPage from './components/MainPage';
import LoginPage from './components/LoginPage'
export default class App extends Component {
render() {
return (
<Router>
<Switch>
<Route exact path="/">
<Redirect to="/login" />
</Route>
<LoginLayoutRoute path="/login" component={LoginPage} />
<MainLayoutRoute path="/home" component={MainPage} />
</Switch>
</Router>
);
}
}
But when i refresh the page, it turned blank like this:
Before i refresh page
After i refresh page
How can i fix this ?
When pressing {Link} and changing Route, the header component NavBar keeps rerendering, even when is outside the Switch component from react-router-dom.
here are the files:
Main index.js file:
import React from 'react'
import styles from './styles.css'
import {Route, Switch} from 'react-router-dom'
import Home from './Home'
import Settings from './Settings'
import Layout from './Layout'
import Contact from './Contact'
import NavBar from 'App/components/NavBar'
export default class MainHome extends React.Component {
static propTypes = {}
render() {
return (
<div className={styles.container}>
<NavBar />
<Switch>
<Route path="/settings" component={Settings} />
<Route path="/contact" component={Contact} />
<Route path="/" component={Home} />
</Switch>
</div>
)
}
}
Home.js
import React from 'react'
import styles from './styles.css'
import {Link} from 'react-router-dom'
export default class Home extends React.Component {
static propTypes = {}
render() {
return (
<div className={styles.container}>
<h1>Hello world</h1>
<Link to="/contact">Contact</Link>
</div>
)
}
}
Contact.js
import React from 'react'
import styles from './styles.css'
import {Link} from 'react-router-dom'
export default class Contact extends React.Component {
static propTypes = {}
render() {
return (
<div className={styles.container}>
Contact
<Link to="/">Home</Link>
</div>
)
}
}
The current project is pretty simple: the index.js file has inside the Home and Contact components, and the NavBar component as a header outside the Switch.
#MattyJ I'm using react-router-dom#^4.2.1. The component with the Router looks like this:
import React from 'react'
import Root from 'App/Root'
import Pages from './Pages'
import {BrowserRouter} from 'react-router-dom'
export default class App extends React.Component {
render() {
return (
<BrowserRouter key={Math.random()}>
<Root>
<Pages />
</Root>
</BrowserRouter>
)
}
}
Pages encapsulates two components: App, where is located the Switch component from my question, and Auth for managing autentication:
import React from 'react'
import authRouteRegex from './Auth/routeRegex'
import {withRouter} from 'react-router'
import PropTypes from 'prop-types'
import DynamicComponent from 'App/components/DynamicComponent'
import App from './App'
#withRouter
export default class Pages extends React.Component {
static propTypes = {
location: PropTypes.object
}
render() {
if (authRouteRegex.test(this.props.location.pathname)) {
const Component = DynamicComponent(() => import('./Auth'))
return <Component />
}
return <App />
}
}
I use react router and I can see Signup link on the screen
But when I press this link nothing heppends , Tell me why please.
Main.js
import ReactDOM from 'react-dom';
import React from 'react';
//import { Router, Route, hashHistory } from 'react-router';
import { BrowserRouter, Route } from 'react-router-dom'
import App from './components/App.jsx';
import WizardIndex from './components/WizardIndex.js';
ReactDOM.render(
<BrowserRouter>
<App path="/" component={App}>
<Route path="/signup" component={ WizardIndex }/>
</App>
</BrowserRouter>,
document.getElementById('mount-point')
);
App.jsx
import React from 'react';
import { Link } from 'react-router-dom';
const App = React.createClass({
render: function(){
return (
<div className='App'>
<div className='menu-bar'>
<div className='menu-item'>
<h3>App</h3>
<Link to='/signup'>Signup</Link>
</div>
<div className='content'>
{ this.props.children }
</div>
</div>
</div>
);
}
});
export default App;
WisardIndex.js
import React from "react";
import ReactDOM from "react-dom";
import { Provider } from "react-redux";
import { Values } from "redux-form-website-template";
import store from "./store";
import showResults from "./showResults";
import WizardForm from "./WizardForm";
const Index = React.createClass({
render(){
return (
<h3>123</h3>
);
}
});
export default Index;
I can not understand I setting up this.props.children in App.jsx. I include Route And Think everything doing by the rules, but nothing in the result
First of all first, if you can compile and run given source code then that means you are working with React's very old version that's because of there is no such thing as React.createClass anymore. Update it.
Second I think you misunderstood the concept of react-router-dom. That line contains <App path="/" ... effects nothing because of you cannot assign path nor component props to App. If you are rendering App component as a child of BrowserRouter that means "Im surrounding every route with one component and it's the App Component. App component should render every route as a child."
I'm assuming that you will create your components as Class Components then the right code would be like this :
Main.js :
import ReactDOM from 'react-dom';
import React from 'react';
//import { Router, Route, hashHistory } from 'react-router';
import { BrowserRouter, Route } from 'react-router-dom'
import App from './components/App.jsx';
import WizardIndex from './components/WizardIndex.jsx';
ReactDOM.render(
<BrowserRouter>
<App>
<Route path="/signup" component={ WizardIndex }/>
</App>
</BrowserRouter>,
document.getElementById('mount-point')
);
App.jsx :
import React from "react";
import { Link } from "react-router-dom";
class App extends React.Component {
render() {
const { children } = this.props;
return (
<div className="App">
<div className="menu-bar">
<div className="menu-item">
<h3>App</h3>
<Link to="/signup">Signup</Link>
</div>
<div className="content">{children}</div>
</div>
</div>
);
}
}
export default App;
WizardIndex.jsx :
import React from "react";
import ReactDOM from "react-dom";
class WizardIndex extends React.Component {
render() {
return <h3>123</h3>;
}
}
export default WizardIndex;
Actually i have written it for you in codesandbox, you can check the working code for your situation here:
https://codesandbox.io/s/rr1nv610wp
I am designing a website in which the header is the same for three pages.
By default the fist page should have the following components
Header QueryList
and on click of a button present in Header the QueryList component should change to FindExpert.js.
Along with the change in Page, the URL also changes on the click of a button.
Header FindExpert
Since header is present in both the screens and I don't want to call the component again and again in every js file.So, I used ternary operator in the header.js file so that I can route in half of the page.
App.js
import React, { Component } from 'react';
import {BrowserRouter,Route,Router,Switch} from 'react-router-dom';
import {Header} from './Header.js';
import {FindExpert} from './FindExpert.js';
class App extends Component {
render() {
return (
<div>
<BrowserRouter>
<Switch>
<Route exact path="/" component={Header} />
<Route path="/findexpert" component={FindExpert} />
</Switch>
</BrowserRouter>
</div>
);
}
}
export default App;
Header.js
import React, { Component } from 'react';
import {Constants} from './constants.js';
import {QueryList} from './QueryList.js';
import {FindExpert} from './FindExpert.js';
export class Header extends React.Component{
constructor(props) {
super(props);
this.state = {
ProfileData: {},
profileImage: "profile-pic.svg",
isClicked:false
};
this.findExpertClicked = this.findExpertClicked.bind(this);
this.findExpertPage=this.findExpertPage.bind(this)
}
findExpertClicked() {
console.log("Find expert clicked");
this.setState({
isClicked:true
})
}
findExpertPage(){
this.props.history.push('/findexpert');
}
render(){
return(
<div>
<div className="col-md-12 HeaderBar">
<div className="HeaderContent">
</div>
</div>
<div className="ProfileHeader">
<div className="profileImageDiv">
<img src={this.state.profileImage} className="profileImageSrc" alt="Alternate"></img>
</div>
</div>
<div className="headerButtons">
<div className="ExBtnDiv" onClick={this.findExpertClicked}><span className="ExBtn">Find Expert</span></div>
</div>
</div>
<div>{(this.state.isClicked===false)?<div><QueryList/></div> :<div>{this.findExpertPage()}</div>}</div>
</div>
)
}
}
And in FindExpert.js, suppose I have a simple Hello world.
import React, { Component } from 'react';
import {Header} from './Header.js';
import {Constants} from './constants.js';
export class FindExpert extends React.Component{
render(){
return(
<div>
Hello world
</div>
)
}
}
Through the above code, the QueryList comes below the Header as expected but when clicked on the find expert button, the whole page changes.
Since I don't want to call header.js in both the files, is there a way to keep the header constant and change the contents below it as well as change the url when find expert button is clicked.
You have to create separate components for Header and the content to be shown on the homepage. And directly render the Header component inside App.js
This way Header component will always be rendered and only the page content would change according to the current route.
For example:
import React, { Component } from 'react';
import {BrowserRouter,Route,Router,Switch} from 'react-router-dom';
import {Header} from './Header.js';
import HomePage from './HomePage.js';
import {FindExpert} from './FindExpert.js';
class App extends Component {
render() {
return (
<div>
<Header />
<BrowserRouter>
<Switch>
<Route exact path="/" component={HomePage} />
<Route path="/findexpert" component={FindExpert} />
</Switch>
</BrowserRouter>
</div>
);
}
}
export default App;
I'm trying to set up my react.js environment to build a UI Toolkit. I'm using react-router, but for some reason the URL changes when I click on the links rendered from Index.js, but the content stays the same. It just continues displaying the content from the index.js page instead of changing to the content of the link I clicked. I'm not getting any error messages on the console.
main.js
import React from 'react';
import ReactDOM from 'react-dom';
import { Router, browserHistory } from 'react-router';
import routes from './routes';
function run(){
const reactMount = document.getElementById('app');
ReactDOM.render(<Router onUpdate={() => window.scrollTo(0, 0)} history= {browserHistory} routes={routes}/>, reactMount );
}
new Promise((resolve) => {
if (window.addEventListener) {
window.addEventListener('DOMContentLoaded', resolve);
} else {
window.attachEvent('onload', resolve);
}
}).then(run)
routes.js
import React from 'react';
import { IndexRoute, Route } from 'react-router';
import Index from './pages/Index';
import Text from './pages/Text';
import Icon from './pages/Icon';
var routes = (
<Route path="/" component={Index}>
<Route path="/Text" component={Text} />
<Route path="/Icon" component={Icon} />
</Route>
);
export default routes;
pages/Index.js
import React from 'react';
import {Link} from 'react-router';
class Index extends React.Component {
render() {
return (
<div>
<ul role="nav">
<li><Link to="/Text">Text</Link></li>
<li><Link to="/Icon">Icon</Link></li>
</ul>
</div>
)
}
}
export default Index;
pages/Text.js
import React from 'react';
class Text extends React.Component {
render() {
return (
<div>
<h1>Text</h1>
</div>
)
}
}
export default Text;
Two things here:
The nested routes Text and Icon in your route configuration shouldn't have / before them. It should be like this: <Route path="Text" component={Text} />.
In your container component (Index) you need to access this.props.children so that the component knows to render it's children (the nested routes).
// Index.js
return (
<div>
<ul role="nav">
<li><Link to="/Text">Text</Link></li>
<li><Link to="/Icon">Icon</Link></li>
</ul>
{ this.props.children }
</div>
)