我有这个应用程序,每次用户通过前面的突变操作登录或注销时,我都必须自己刷新浏览器以更新导航栏,也许我在main.push之前缺少refetchQueries方法。然后,如果我通过单击导航栏上的退出按钮注销,则必须由我自己将浏览器刷新为在导航组件上工作的条件。
// 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);
我的路线在导航栏组件中:
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)
答案 0 :(得分:1)
所以这些看起来像是两个不同的问题。
在登录方案中,您似乎有一条嵌套的路线。该页面不会重定向,因为您在同一子路由器中没有为/
定义的路由。您需要将登录路线上移到与本国路线相同的级别。
在退出场景中,这更多是一个一般的React问题,您不会做任何会触发渲染的事情。例如,如果您将登录状态更改为NavBar
的本地状态,则可以在登录状态更改时强制组件重新呈现,例如
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);
}
}
...
}
登录时,当然需要保持此状态同步,以使其正常工作,但您能理解。