How hide component from another component start render through route on react - reactjs

I would like to hide a component when another component is routing
for more specific, i have a fixed bottom nav that i want to hide when a component is been route by user, in this case its a comment box
My first option was trying on the parent component with browserhistory and history.listen, and componning a string with math.params for get a match between, and this change the state of parent, witch will hide the bottomnav, and the code wrote was trying through a cyclelife passing props, but nothing, anyone can help me please?
class App extends React.Component {
constructor(props){
super(props);
this.state = {
showBottomNav: true
}
this.hideBottomNav = this.hideBottomNav.bind(this)
}
hideBottomNav= () => {
this.setState({
showBottomNav: false
})
}
render() {
return (
<Router>
<NavBar />
<Switch>
<Route path='/' exact component={Home} />
<Route path='/wars' exact component={Tournament} />
<Route path='/shop' exact component={Shop} />
<Route path='/library' exact component={Library} />
<Route
path='/:id'
exact
render={ props => <ExpandedPost {...props} parentMethod={() => this.hideBottomNav()} />}
/>
</Switch>
<BottomNav />
</Router>
);
}
}
export default App;
And the children Component
export default function PostReview(props) {
const classes = useStyles();
useEffect(() => {
props.parentMethod()
},[props])
return (
<div>....

Related

React-router - How to use multiple private routes?

My project have 2 different roles and both need login.
So I created 2 login pages and 2 private routes are Auth and Trainee
The problem is even I type an url is not children of Auth route it will go through Auth then it all wrong after that
<BrowserRouter>
<Switch>
<Route
exact
path={LoginForAuthPath}
component={LoginForAuthComponent}
/>
<Route
exact
path={LoginForTraineePath}
component={LoginForTraineeComponent}
/>
<Auth>
<Route
exact
path={SomeAuthPath}
component={SomeAuthComponent}
/>
</Auth>
<Trainee>
<Route
exact
path={SomeTraineePath}
component={SomeTraineeComponent}
/>
</Trainee>
</Switch>
</BrowserRouter>
class Auth extends React.Component {
constructor(props) {
super(props);
this.state = {
loggedIn: isLoggedIn(),
};
}
render() {
return this.state.loggedIn ? (
<Route children={this.props.children} />
) : (
<Redirect to={LoginPath} />
);
}
}
The issue here is that Switch renders the first matching component/Route within its children.
Since Auth is rendered unconditionally and is a valid component, it stops matching after Auth is rendered and never reaches Trainee
You should perhaps change your implementation of Auth and Trainee so that they both use Route as the direct child
class Auth extends React.Component {
constructor(props) {
super(props);
this.state = {
loggedIn: isLoggedIn(),
};
}
render() {
const {component: Component, ...rest } = this.props;
return <Route {...rest} render={(rProps) => this.state.loggedIn? <Component {...rProps}/>: <Redirect to={LoginPath} />} />
}
}
Similarly change the implementation of Trainee and use it like
<BrowserRouter>
<Switch>
<Route
exact
path={LoginForAuthPath}
component={LoginForAuthComponent}
/>
<Route
exact
path={LoginForTraineePath}
component={LoginForTraineeComponent}
/>
<Auth
exact
path={SomeAuthPath}
component={SomeAuthComponent}
/>
<Trainee
exact
path={SomeTraineePath}
component={SomeTraineeComponent}
/>
</Switch>
</BrowserRouter>

React routing - Routes independent of parent routing files

I am defining the routes in react
Global ones in the app-routes.js file and other in their respective components.
app.js
render() {
return (
<div className="App-wrap">
<AppRoutes/>
</div>
); }
app-route.js
export class AppRoutes extends React.Component {
render() {
return (
<Router>
<Switch>
<Route path="/" component={LayoutComponent} />
</Switch>
</Router>
);
}
}
layout-component.js
I have placed my header here for navigation
export class LayoutComponent extends React.Component {
render() {
return (
<LayoutWrap>
<HeaderComponent> </HeaderComponent>
<LayoutRoutes />
</LayoutWrap>
);
}
}
layout.routing.js
export class LayoutRoutes extends React.Component {
render() {
return (
<Switch>
<Route path="/" exact >
<Redirect to="/users"/>
</Route>
<Route path="/users" name="Users" component={UserComponent} />
<Route path="/permissions" name="Permissions" component={PermissionComponent} />
</Switch>
);
}
}
Now the issue is, when i am defining my child routes, my child routes are dependent on parent
i.e. i have to write parent's previous url in child.
If i change my app-routes.js path from "" to layout my routing will not work.
<Route path="/layout" component={LayoutComponent} />
How to solve the issue?
When you are defining your child Routes, you need to prefix the parent route path before it for these to work. For this you can make use of match.path from props like
export class LayoutRoutes extends React.Component {
render() {
const { match } = this.props;
return (
<Switch>
<Route path={match.path} exact render ={(props) => <Redirect to="/users"/>} />
<Route path=`${match.path}/users` name="Users" component={UserComponent} />
<Route path=`${match.path}/permissions` name="Permissions" component={PermissionComponent} />
</Switch>
);
}
}

React router open modal

I'm new to react and redux world. I have a question regarding react router. Following is my App component.
class App extends React.PureComponent {
render() {
return (
<div>
<Switch>
<Route exact path="/" component={HomePage} />
<Route exact path="/callback" component={CallbackPage} />
<Route exact path="/list" component={List} />
<Route component={NotFoundPage} />
</Switch>
</div>
);
}
}
export default App;
My list class looks like this:
export class List extends React.PureComponent {
constructor(props) {
super(props);
this.state = {
isOpen: false,
};
this.depositHandleToggle = this.depositHandleToggle.bind(this);
}
depositHandleToggle = () => {
this.props.dispatch(push(`${this.props.match.url}/deposit`));
}
render() {
const { match } = this.props;
return (
<div>
<Route path={`${match.url}/deposit`} component={Modal} />
<button onClick={this.depositHandleToggle}>Open Modal</button>
</div>
);
}
}
export default List;
So my question is: when i click the button in List container, why my router can't find this url 'localhost:xxx/list/deposit'? it renders the App component but it never goes back to List component. Is it possible to have the custom routes inside my list container? Am i doing something wrong? Please someone help me with this.
I hope you understand my question. Thanks in advance.
ANSWER:
I found the answer, the issue was in my App component list route. I was having the 'exact' keyword, that's why route inside my list component was not working. Following way is the correct way.
<Route path="/list" component={List} />
I hope this will help someone.
import { Link } from 'react-router-dom';
class App extends React.PureComponent {
render() {
return (
<div>
<Switch>
<Route exact path="/" component={HomePage} />
<Route exact path="/callback" component={CallbackPage} />
<Route exact path="/list" component={List} />
<Route exact path="/list/deposit" component={Modal} />
<Route component={NotFoundPage} />
</Switch>
</div>
);
}
}
export default App;
export class List extends React.PureComponent {
constructor(props) {
super(props);
}
render() {
const { match } = this.props;
return (
<div>
<Link to={'/deposit'}>Open Modal</Link>
);
}
}
export default List;
in that component you should handle modal open close.

React: Hide a Component on a specific Route

New to React:
I have a <Header /> Component that I want to hide only when the user visit a specific page.
The way I designed my app so far is that the <Header /> Component is not re-rendered when navigating, only the page content is, so it gives a really smooth experience.
I tried to re-render the header for every route, that would make it easy to hide, but I get that ugly re-rendering glitch each time I navigate.
So basically, is there a way to re-render a component only when going in and out of a specific route ?
If not, what would be the best practice to achieve this goal ?
App.js:
class App extends Component {
render() {
return (
<BrowserRouter>
<div className="App">
<Frame>
<Canvas />
<Header />
<Main />
<NavBar />
</Frame>
</div>
</BrowserRouter>
);
}
}
Main.js:
const Main = () => (
<Switch>
<Route exact activeClassName="active" path="/" component={Home} />
<Route exact activeClassName="active" path="/art" component={Art} />
<Route exact activeClassName="active" path="/about" component={About} />
<Route exact activeClassName="active" path="/contact" component={Contact} />
</Switch>
);
I'm new to React too, but came across this problem. A react-router based alternative to the accepted answer would be to use withRouter, which wraps the component you want to hide and provides it with location prop (amongst others).
import { withRouter } from 'react-router-dom';
const ComponentToHide = (props) => {
const { location } = props;
if (location.pathname.match(/routeOnWhichToHideIt/)){
return null;
}
return (
<ComponentToHideContent/>
)
}
const ComponentThatHides = withRouter(ComponentToHide);
Note though this caveat from the docs:
withRouter does not subscribe to location changes like React Redux’s
connect does for state changes. Instead, re-renders after location
changes propagate out from the component. This means that
withRouter does not re-render on route transitions unless its parent
component re-renders.
This caveat not withstanding, this approach seems to work for me for a very similar use case to the OP's.
Since React Router 5.1 there is the hook useLocation, which lets you easily access the current location.
import { useLocation } from 'react-router-dom'
function HeaderView() {
let location = useLocation();
console.log(location.pathname);
return <span>Path : {location.pathname}</span>
}
You could add it to all routes (by declaring a non exact path) and hide it in your specific path:
<Route path='/' component={Header} /> // note, no exact={true}
then in Header render method:
render() {
const {match: {url}} = this.props;
if(url.startWith('/your-no-header-path') {
return null;
} else {
// your existing render login
}
}
You can rely on state to do the re-rendering.
If you navigate from route shouldHide then this.setState({ hide: true })
You can wrap your <Header> in the render with a conditional:
{
!this.state.hide &&
<Header>
}
Or you can use a function:
_header = () => {
const { hide } = this.state
if (hide) return null
return (
<Header />
)
}
And in the render method:
{this._header()}
I haven't tried react-router, but something like this might work:
class App extends Component {
constructor(props) {
super(props)
this.state = {
hide: false
}
}
toggleHeader = () => {
const { hide } = this.state
this.setState({ hide: !hide })
}
render() {
const Main = () => (
<Switch>
<Route exact activeClassName="active" path="/" component={Home} />
<Route
exact
activeClassName="active"
path="/art"
render={(props) => <Art toggleHeader={this.toggleHeader} />}
/>
<Route exact activeClassName="active" path="/about" component={About} />
<Route exact activeClassName="active" path="/contact" component={Contact} />
</Switch>
);
return (
<BrowserRouter>
<div className="App">
<Frame>
<Canvas />
<Header />
<Main />
<NavBar />
</Frame>
</div>
</BrowserRouter>
);
}
}
And you need to manually call the function inside Art:
this.props.hideHeader()
{location.pathname !== '/page-you-dont-want' && <YourComponent />}
This will check the path name if it is NOT page that you DO NOT want the component to appear, it will NOT display it, otherwise is WILL display it.

ReactJS How to use Router's props inside app.js file

The app.js file of my project is following. For all other components I used this.props.history.push('/') to redirect to the specific path and it works as those components receives the props. But in this app.js I have tried to console the props values inside constructor, componentWillMount and render but all gives null array. Is there any way to use this.props.history.push('/') inside app.js ?
class App extends Component {
constructor(props) {
super(props);
this.state = {};
console.log(this.props)
}
componentWillMount(){
console.log(this.props)
this.props.history.push('/')
}
render() {
console.log(this.props)
return (
<Router>
<div className="App">
<Route exact path='/' render={(props) => <Login {...props} />} />
<Route exact path='/dashboard' render={(props) => <Dashboard {...props}/>}/>
</div>
</Router>
);
}
}
export default App;
use withRouter
import { withRouter } from 'react-router-dom'
class App extends Component {
constructor(props) {
super(props);
this.state = {};
console.log(this.props)
}
componentWillMount(){
console.log(this.props)
this.props.history.push('/')
}
render() {
console.log(this.props)
return (
<Router>
<div className="App">
<Route exact path='/' render={(props) => <Login {...props} />} />
<Route exact path='/dashboard' render={(props) => <Dashboard {...props}/>}/>
</div>
</Router>
);
}
}
export default withRouter(App);
that will give you access to the history object and allow you to push to new routes. (I tested and verified before posting, so I know this works).
import it on the top of the file, then wrap App with it in the export default

Resources