我有一个 Header
组件,它将在导航栏中显示下拉登录、注册和注销。这将被视为组件 A。
而且我还有 Sign In
组件,在我的想法中被认为是组件 B。它将在内容正文中显示一个“登录方式”框和一个“登录”按钮。
我想达到什么目标?如果我登录 -> 我将收到一个令牌,如果在标题处,我有一个令牌,它只会显示注销,如果令牌 = 空,它只会显示登录和注册。
我取得了什么成就?
如果我从标题中按下注销 - 这是下拉导航栏,我可以将令牌的状态设置为 null
,因此状态更改,它将再次呈现组件,这将更新并显示Sign-up and Sign-in since token = null
因为我删除了 localStorage
问题是:
这不适用于 Sign-in
组件,因为它来自一个完全不同的组件,它与标题没有任何关系。如果我从 Sign In
组件按下登录按钮,我可以获得令牌并将其推送到 localStorage,但我必须手动刷新网页以便它可以再次呈现,我找不到方法将该令牌传递到标头中,以便它可以作为状态接收以使其再次呈现。
我需要帮助,谢谢。我认为有一种方法,即使用 Redux 或其他东西来存储状态,但我不知道如何使用它,所以请问有什么方法可以仅使用 React 来做到这一点?
Header
组件:
export default function Header(props) {
const [token, setToken] = useState(localStorage.getItem("token"));
const onClickToSignOut = () => {
localStorage.removeItem("token");
setToken(null);
};
useEffect(() => {
setToken(token);
}, [token]);
return (
<div className="header">
<div className="logo">
<img src="./Demo/assets/images/logo.png" alt="SCC Logo" />
</div>
<ul id="nav">
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/contact">Contact</Link>
</li>
<li>
<Link to="/quiz-topics">Quiz Topic</Link>
</li>
<li>
<a href="#">
<i className="ti-user"></i>
</a>
<ul className="subnav">
{!token ? (
<>
<li>
<Link to="/sign-in">Sign in </Link>
</li>
<li>
<Link to="/sign-up">Sign up</Link>
</li>
</>
) : (
<>
<li>
<Link to="/sign-in" onClick={onClickToSignOut}>
Log out
</Link>
</li>
</>
)}
</ul>
</li>
</ul>
<div id="mobile-menu" className="mobile-menu-btn">
<i className="menu-icon ti-menu"></i>
</div>
</div>
);
}
SignIn
组件:
class SignIn extends Component {
constructor(props) {
super(props);
this.state = {
username: "",
password: "",
};
}
handleOnChange = (event) => {
let { name, value } = event.target;
this.setState({
[name]: value,
});
};
handleOnSubmit = (event) => {
event.preventDefault();
let { username, password } = this.state;
if (username === "" && password === "") {
toast.warning(`Please enter all the fields`);
} else if (username === "") {
toast.error(`Please enter your username`);
} else if (password === "") {
toast.error(`Please enter your password`);
} else {
callApi("sign-in", "POST", {
username: username,
password: password,
}).then((res) => {
if (res.data.token) {
localStorage.setItem("token", res.data.token);
this.setState({ token: res.data.token });
// I want to do something in here that can trigger the Header component after I receive the token when I'm pressing submit at the login//
toast.success(`Successfully log in.`);
this.props.history.push("/");
} else {
toast.error(`There is something wrong, please try again.`);
}
});
}
};
render() {
return (
<div className="register-page height-fixed">
<div id="toast"></div>
<div
style={{
background:
"url('/Demo/assets/images/slider/slider1.jpg'), no-repeat, fixed, center",
height: "100vh",
}}
>
<div className="register-section vertical-center">
<h2>Sign in</h2>
<div className="user-info">
<form onSubmit={this.handleOnSubmit}>
<div className="row">
<div className="username-line">
<div className="col-25">
<label htmlFor="username">Username</label>
</div>
<div className="col-75">
<input
onChange={this.handleOnChange}
type="text"
placeholder="Enter username"
name="username"
value={this.state.username}
/>
</div>
</div>
</div>
<div className="row">
<div className="password-line">
<div className="col-25">
<label htmlFor="password">Password</label>
</div>
<div className="col-75">
<input
onChange={this.handleOnChange}
type="password"
placeholder="Enter password"
name="password"
value={this.state.password}
/>
</div>
</div>
</div>
<div className="user-info-button">
<Link to="/sign-up">
<button className="btn btn--success btn--danger">
Sign up
</button>
</Link>
<button type="submit">Log in</button>
</div>
</form>
</div>
</div>
</div>
</div>
);
}
}
export default SignIn;