React - HeaderComponent không thay đổi sau khi đăng nhập?
Tôi có một TodoComponentcái được viết để hiển thị một số liên kết nhất định trên thanh điều hướng trong HeaderComponent tùy thuộc vào trạng thái hiện tại của người dùng - cho dù đã đăng nhập hay đã đăng xuất.
class TodoApp extends Component {
render = () => {
return (
<div className="TodoApp">
<Router>
<HeaderComponent />
<Switch>
<Route path="/" exact component={LoginComponent} />
<Route path="/login" exact component={LoginComponent} />
<AuthenticatedRoute path="/welcome/:name" exact component={WelcomeComponent} />
<AuthenticatedRoute path="/todos/" exact component={ListTodosComponent} />
<AuthenticatedRoute path="/logout" exact component={LogoutComponent} />
<Route component={ErrorFuncComponent} />
</Switch>
<FooterComponent />
</Router>
</div>
)
}
}
Tôi cảm thấy HeaderComponentnó không tự hiển thị lại sau khi người dùng đã đăng nhập.
class HeaderComponent extends Component {
render() {
const isUserLoggedIn = AuthenticationService.isUserLoggedIn()
console.log(isUserLoggedIn)
return (
<header>
<nav className="navbar navbar-expand-md navbar-dark bg-dark">
<div><a href="http://localhost:3000" className="navbar-brand">Todo Management</a></div>
<ul className="navbar-nav">
{isUserLoggedIn && <li><Link className="nav-link" to="/welcome/in28minutes">Home</Link></li>}
{isUserLoggedIn && <li><Link className="nav-link" to="/todos">Todos</Link></li>}
</ul>
<ul className="navbar-nav navbar-collapse justify-content-end">
{!isUserLoggedIn && <li><Link className="nav-link" to="/login">Login</Link></li>}
{isUserLoggedIn && <li><Link className="nav-link" onClick={AuthenticationService.logoutAuthenticatedUser} to="/logout">Logout</Link></li>}
</ul>
</nav>
</header>
)
}
}
vì thành phần LogIn không bắt buộc? (Tôi có nên buộc các thành phần khác không? Tôi không chắc đây có phải là cách chính xác để thực hiện mọi việc)
Đoạn trích của LoginComponent.jsx
handleLoginButtonClick = () => {
if (this.state.username === 'zaid' && this.state.password === 'khan') {
AuthenticationService.registerAuthenticatedUser(this.state.username, this.state.password)
// window.location.reload(false);
this.props.history.push(`/welcome/${this.state.username}`) //String templating //this.props.history.push("/welcome/"+this.state.username)
this.setState(
{ isLoginSuccess: true, isLoginFailed: false }, function () {
console.log(this.state);
}
)
}
else {
this.setState(
{ isLoginSuccess: false, isLoginFailed: true }, function () {
console.log(this.state);
}
)
}
// console.log(this.state)
}
Làm cách nào để cập nhật HeaderComponent (về cơ bản gọi renderlại phương thức sau khi người dùng đăng nhập?!?!).
Tái bút Tôi nghĩ có thể có một cách khác để làm điều đó liên quan đến việc tự động thực hiện một số hành động dựa trên một sự kiện. Tôi chỉ không biết làm thế nào nó sẽ phù hợp với những gì tôi đã làm cho đến nay. Tôi mới sử dụng React.
Anh chàng này phải đối mặt với vấn đề tương tự (nhưng giải thích nó kém IMO): bật xác thực người dùng dựa trên liên kết menu không hoạt động trong reactjs
Trả lời
Các thành phần kết xuất lại nếu nó phát hiện bất kỳ thay đổi nào trong Trạng thái hoặc Đạo cụ, đây là những gì so sánh nông làm, vì vậy để kết xuất lại thành phần, nó sẽ phụ thuộc vào một thành phần nếu những điều này, vì vậy những gì bạn có thể làm là sử dụng isLoginSuccess và chuyển nó trở lại tới TodoComponent và sau đó gửi nó dưới dạng đạo cụ tới HeaderComponent như thế này:
class TodoApp extends Component {
state = {isLoginSuccess:false}
render = () => {
return (
<div className="TodoApp">
<Router>
<HeaderComponent isLoginSuccess={this.state.isLoginSuccess}/>
<Switch>
<Route path="/" exact component={() => <LoginComponent isAuthed={true} onLogin={(status)=> this.setState({isLoginSuccess:status})}/>} />
...
</Router>
</div>
)
}
}
Trong LoginComponent
handleLoginButtonClick = () => {
if (this.state.username === 'zaid' && this.state.password === 'khan') {
...
this.props.onLogin(true);
...
}
else {
this.props.onLogin(false);
...
}
}
Trong HeaderComponent, thay thế isUserLoggedIn bằng isLoginSuccess:
class HeaderComponent extends Component {
render() {
let { isLoginSuccess } = this.props;
...
return (
<header>
<nav className="navbar navbar-expand-md navbar-dark bg-dark">
<div><a href="http://localhost:3000" className="navbar-brand">Todo Management</a></div>
<ul className="navbar-nav">
{isLoginSuccess && <li><Link className="nav-link" to="/welcome/in28minutes">Home</Link></li>}
...
</nav>
</header>
)
}
}
Lưu ý: Sử dụng Redux hoặc Context thay vì truyền đạo cụ giữa các thành phần sẽ có cấu trúc hơn và dễ xử lý hơn
Bạn không nên giữ trạng thái xác thực của mình trong một lớp bên ngoài. React phát hiện thay đổi chỉ kích hoạt nếu trạng thái hoặc đạo cụ khác nhau (so sánh nông). Nó không thể phát hiện những thay đổi trong một lớp bên ngoài. Ví dụ, một trạng thái như vậy có thể được quản lý bằng React Context.
const AuthContext = React.createContext()
function AuthProvider(props) {
const login = () => {}
const register = () => {}
const logout = () => {}
const isLoggedIn = ()=>{}
return (
<AuthContext.Provider value={{data, login, logout, register, isLoggedIn }} {...props} />
)
}
export function withAuthContext(Component) {
return function WrapperComponent(props) {
return (
<AuthContext.Consumerr>
{state => <Component {...props} context={state} />}
</AuthContext.Consumer>
);
};
}
export {AuthProvider, withAuthContext}
class HeaderComponent extends Component {
render() {
const isUserLoggedIn = props.context.isLoggedIn()
return (
<header>
<nav className="navbar navbar-expand-md navbar-dark bg-dark">
<div><a href="http://localhost:3000" className="navbar-brand">Todo Management</a></div>
<ul className="navbar-nav">
{isUserLoggedIn && <li><Link className="nav-link" to="/welcome/in28minutes">Home</Link></li>}
{isUserLoggedIn && <li><Link className="nav-link" to="/todos">Todos</Link></li>}
</ul>
<ul className="navbar-nav navbar-collapse justify-content-end">
{!isUserLoggedIn && <li><Link className="nav-link" to="/login">Login</Link></li>}
{isUserLoggedIn && <li><Link className="nav-link" onClick={props.context.logout} to="/logout">Logout</Link></li>}
</ul>
</nav>
</header>
)
}
}
export default withAuthContext(HeaderComponent)
Hãy nhớ bọc toàn bộ cây React của bạn với AuthProvider.