i have this app that everytime the user login or logout by a mutation operation in the front i have to refresh the browser by myself to update the navbar, maybe i missing refetchQueries method before the history.push in the main function. then if i logout by clicking the signout button at navbar the same i have to refresh by myself the browser to the conditionals working at the navigation component.
// React apollo
import { graphql } from 'react-apollo';
import * as compose from 'lodash.flowright';
// React router
import { withRouter } from 'react-router-dom';
// import mutations
import mutations from './mutations';
// React bootstrap
import { Container, Row, Form, Button } from 'react-bootstrap';
// Import Style
import './style.css';
class LoginForm extends React.Component {
state = {
login_credentials: {}
}
get_data = async(e) => {
e.preventDefault();
const { name, value } = e.target;
const data = { [name]: value };
const newData = { ...this.state.login_credentials, ...data };
this.setState({
login_credentials: newData
});
}
submit = async(e) => {
e.preventDefault();
const { signinUser } = this.props;
const { login_credentials } = this.state;
try {
let variables = login_credentials;
const response = await signinUser({variables});
const get_token = response.data.signinUser.token;
// setting localStorage
localStorage.setItem('token', get_token);
this.props.history.push('/');
} catch(error) {
console.log(error);
}
}
render() {
return(
<Fragment>
<Container>
<Form className="form-container">
<h2 className="text-center pb-4">Ingreso</h2>
<Form.Group controlId="formBasicEmail">
<Form.Control name='email' onChange={e => this.get_data(e)} type="email" placeholder="Email" />
</Form.Group>
<Form.Group controlId="formBasicPassword">
<Form.Control name='password' onChange={e => this.get_data(e)} type="password" placeholder="Contraseña" />
</Form.Group>
<div className="text-center">
<Button className="button-login" variant="primary" onClick={e => this.submit(e)} type="submit">
Ingresa
</Button>
</div>
</Form>
</Container>
</Fragment>
);
}
}
export default compose(
withRouter,
graphql(mutations.signinUser, { name: 'signinUser' }),
)(LoginForm);
My routes are in the navbar component:
class NavbarLayout extends React.Component {
signOut = async(e) => {
e.preventDefault();
const { signoutUser } = this.props;
try {
await signoutUser();
localStorage.removeItem('token');
} catch(error) {
console.log(error);
}
}
render() {
const user_token = localStorage.getItem('token') || '';
return(
<Fragment>
<Navbar bg="light" expand="lg">
<Navbar.Brand href="#home">Sample App</Navbar.Brand>
<Navbar.Toggle aria-controls="basic-navbar-nav" />
<Navbar.Collapse id="basic-navbar-nav">
<Nav className="ml-auto">
<Nav.Link><Link to="/">Home</Link></Nav.Link>
{user_token ? (
<Fragment>
<Nav.Link onClick={e => this.signOut(e)}>Salir</Nav.Link>
<Nav.Link>Publicar</Nav.Link>
</Fragment>
):(
<Nav.Link><Link to="/sign-in">Entrar</Link></Nav.Link>
)}
</Nav>
</Navbar.Collapse>
</Navbar>
<Switch>
<Route path="/sign-in" component={LoginPage} />
</Switch>
</Fragment>
);
}
}
export default compose(
graphql(mutations.signoutUser, { name: 'signoutUser' })
)(NavbarLayout)
So these look like two different issues.
In the sign in scenario, it looks like you have a nested routes. The page doesn't redirect because you don't have a route for /
defined within the same sub-Router. You will need to move the sign in route up to the same level as the home route.
In the sign out scenario, this is more of a general React issue, you don't do anything that would trigger a render. For example, if you moved the login state to the local state of your NavBar
then you can force the component to re-render when the login state changes e.g.
class NavbarLayout extends React.Component {
constructor() {
this.state = { loggedIn: false };
}
signOut = async(e) => {
e.preventDefault();
const { signoutUser } = this.props;
try {
await signoutUser();
localStorage.removeItem('token');
this.setState({ loggedIn: false });
} catch(error) {
console.log(error);
}
}
...
}
This state would of course need to be kept in sync when you sign in for this to work properly but you get the idea.