I am using ReactJS with Material-UI, which I am both quite new to using.
I have an AppBar component that is used as a main menu/navigation bar. I would like the title of the AppBar component to reflect the page I'm on. So if I press a button that routes the user to /login , I also want to change the title of the AppBar component to "Login". I have accomplished this but there seem to be some side effects so I doubt it's the proper practice.
At the moment, my AppBar component looks like so:
render() {
let MenuOptionsNotLogged = ({}) => (
<div>
<FlatButton
label="Log In"
containerElement={<Link to="/login" />}
secondary
linkButton
onClick={this.switchToLogin}
/>
</div>
);
return (
<div>
<MuiThemeProvider muiTheme={muiTheme}>
<div className="headerDiv">
<AppBar
className="appBar"
showMenuIconButton={this.state.appBarIcon}
title={this.state.appBarTitle}
iconElementRight={<MenuOptionsNotLogged />}
iconElementLeft={<IconButton><BackIcon /></IconButton>}
/>
</div>
</MuiThemeProvider>
</div>
);
In my constructor, I set the default state of the AppBar(the title and icon):
constructor(props, context) {
super(props, context);
this.switchToLogin = this.switchToLogin.bind(this);
this.state = {
appBarTitle: 'Home',
appBarIcon: false
};
}
And then I have a function which changes the title and icon when the user navigates to the Login page:
switchToLogin() {
this.setState({ appBarTitle: 'Log in' });
this.setState({ appBarIcon: true });
}
The problem
This 'works', but it has some problems if the user refreshes or hits the back button on their browser.
E.g. user navigates to /login, title changes to "Login", user refreshes browser. Then the user will be on /login but the title will reset to "Home".
Same problem with the back button. User can navigate to login, press back, and the title will stay as "Login" as opposed to "Home"
I see you have a Link component. My answer assumes you use react-router.
The problem is that your appBarTitle state is not mapped correctly with the current route.
Also when user refresh the browser, the state of components resets.
if you are not using reat-router 3.0, you can get access to the current route through this.context.location.pathname. You will need to read about how to use context here.
Then you can write a helper function to map pathname to the text you want to display: '/login' -> 'Login', '/' -> 'Home'.
Then the title of your AppBar can just be the value returned from the helper function. You no longer need to keep tract of it in the state.
Just to add, not relating to your question, Reactjs is a declarative style of programming, meaning that, 'switchToLogin then display login title' is discouraged. Tell the component what to render rather than how to.
Related
so I am coding a simple app with react-navigation and I want to code this:
- Home (Tab)
- Profile (Tab)
-- User info (Stack screen)
--- Edit user info (Stack screen) - (screen with input to edit name, email etc...)
When I click save on the EditInfo screen I have a button on the right side of the header Done, this button should navigate back to the UserInfo screen where you can see the updated details.
BUT!
Everything works but when I click Done on the EditInfo screen, it navigates back to Home! Why is that?
Thanks for help
Could you please put the code of the service screen where you call the goBack function, it could be helpful. Generally you just call
You are either using the wrong Navigator comp or your requirements are not clear. Basically, You would like to use the StackNavigator for your desired behavior.
The catch is, DrawerNavigator is used to build up a drawer menu. If you swipe from the left you'll see your navigator drawer containing all of your screens as you can see in the image below
If you add a button on your screen like below, you'll see your menu open.
<Button title="MENU" onPress={() => this.props.navigation.navigate('DrawerOpen')} />
The conclusion is, whenever we use DrawerNavigator we always go back to initial route, which is whatever we defined as the first item or using the initialRouteName key of the second param of the DrawerNavigator.
It's only the StackNavigator that supports this stacking order you would like to achieve, as the name suggests itself.
What you can do is to wrap a new StackNavigator inside one of the screens of the DrawerNavigator. For example:
const AppNavigator = DrawerNavigator({
drawer1: {
screen: drawer1,
}
});
const drawer1 = StackNavigator({
one: { screen: one },
two: { screen: two },
three: { screen: three },
});
Maybe this answer would help you.
In a nutshell: maybe you need to specify backBehaviour param in your Tabs navigator.
I'm trying to implement the route like facebook. Let me explain how some route works on Facebook, When a user is scrolling through his feed at home page, Url is example.com/ then if user clicked any photo in the feed a modal will appear over the feed and the url will change like example.com/photo/?urlparams. When user click the back button or close button, Modal hides itself and url back to previous home page example.com/ without re-rendering the feed.
What I tried is
<Route path='/' exact render={(props) => <PostLists {...props} scroll={scroll} /> } />
<Route path='/post/:id' render={(props) => <Single {...props} scroll={scroll}/> } />
PostLists component has infinte scroll so may have up to 90+ posts. Each post have Link to Single Component like below
<Link to={`/post/${props.post.slug}`} className={`post-title`}>{pTitle}</Link>
Everthing works fine like normal navigation. But I like to show this Single Component in the Modal over the PostsLits Component, by the same time URL should be changed like example.com/post/url-slug
So I replaced Link in the post's title as
<span onClick={titleClick} className={`post-title`}>{pTitle}</span>
const titleClick = () => {
props.toggle(true) //Modal Toggle
return window.history.pushState(null, null, `/post/${props.post.slug}`)
}
This works like what I expected but I'm using window history not the react's history so I cannot listen to the URL change from browser back button. If I click the back button URL changes to previous example.com/ But I'm unable to hide the Modal.
What I want is Every post can have (example.com/post/slug)seperate page to display their content, But when clicking the post from Home Page it should be displayed as Modal and url should change to their respective post url example.com/post/slug on clicking the back button modal should be hidden and PostLists should be displayed.
I have a button in my Header component. When it is clicked, it calls a toggleNav function stored in my context.js. This function changes the state of isNavOpen from false to true. The navgiation then opens. There is no CSS in my project that should allow this behavior. I also don't see any JS code that should allow this behavior either. Could someone tell me what code allows my navigation to open and close?
My codesandbox
This is down to the basic way that React works, when you change the state of a component, it re-renders itself with the new values you've set into state.
Specifically it's this bit of Header.js:
{context.state.isNavOpen && (
<div className="js-nav nav">
...
When the component renders the first time, context.state.isNavOpen is false, and false && anything is still false, so javascript ignores the code after the &&. That means it skips over the menu code.
The second time it renders, after you update the state which is pushed to context and then passed to <Header> as a prop (!), the component re-renders with your menu code.
If you use your browser's dev tools to inspect the DOM before and after you click the button, you'll find that the menu isn't hidden and shown, but rather when you don't see it, it's gone from the DOM altogether.
It's react feature whenever state changes component re-renders
same thing happening here
{context.state.isNavOpen && (
isNavOpen is toggling (true to false), (false to true)
for example - you can check it simply
class Toggle extends React.Component {
state = {
visibility: false
}
toggleVisibility=()=>{
this.setState(prev=>({visibility:!prev.visibility}))
}
render() {
const {visibility} = this.state;
return (
<div>
<button onClick={this.toggleVisibility}>Click Me</button>
<h3>{visibility?'Welcome':''}</h3>
</div>
);
}
};
I have a Login Page(StackNavigator) and a Tabbed pages(TabNavigator).
export const Root = StackNavigator({
LoginScreen: {screen: Login},
Tabs: {screen: Tabs}
},
{
initialRouteName: 'LoginScreen'
}
)
After logging the user in there is still a possibility for the user to go back(to Login Page) by swiping back. What is the way of popping the login route from the Route Stack or disabling the back swipe option. Thanks
Dispatch a reset action instead of the normal navigation dispatch. That way you can set the stack to the state you want it to be after logging in and remove your LoginScreen from the stack.
Example related answers:
Resetting the navigation stack for the home screen (React Navigation and React Native)
Reset navigation history to Login screen using react navigation
The official way to handle it from React Navigation (v6) is to define the screens in the navigator based on an isSignedIn condition so that the Login screen will not exist within the navigator once the isSignedIn variable has been set to true.
For example:
<Stack.Navigator>
{isSignedIn ? (
<Stack.Screen name="Tabs" component={TabsScreen} />
) : (
<Stack.Screen name="Login" component={LoginScreen} />
)}
</Stack.Navigator>
See the Authentication Flows section for more information.
I have a modal page popping up when the user clicks a button, it's working perfectly :
render() {
return (
<div>
<section>
<button onClick={() => this.refs.simpleDialog.show()}>Open Modal</button>
</section>
<SkyLight hideOnOverlayClicked ref="simpleDialog" title="Test Modal">
Text that appears inside the modal page
<Button onClick={() => this.refs.simpleDialog.hide()} >Got It</Button>
</SkyLight>
</div>
)}
But My goal is to open the modal automatically when the user opens the page for the first time.
I don't want to open the modal page by clicking on a button
Question:
Can I use an IIFE (An immediately-invoked function expression) in order to open the modal as soon as the user open the page ?
My approach was to set a boolean to true. Then open the modal if the value is set to true
Library being used for the modal :
https://github.com/marcio/react-skylight
I think what you're looking for is the componentDidMount() lifecycle method:
componentDidMount() {
this.refs.simpleDialog.show();
}
From the React docs:
componentDidMount() is invoked immediately after a component is mounted. Initialization that requires DOM nodes should go here. If you need to load data from a remote endpoint, this is a good place to instantiate the network request. Setting state in this method will trigger a re-rendering.
Feel free to checkout other component lifecycle methods.
To have a model open on component mount, just set isVisible to true
<SkyLight isVisible={true} ref="simpleDialog" title="Test Modal">