React Routerアプリを作成していて、認証を学んでいます。ここにいくつかの部分があります:
ログインコンポーネント(login.jsx)
管理コンポーネント(admin.jsx)
ナビゲーションバーの認証ボタン(authbutton.jsx)
ログインから管理者まですべてうまく機能します。私の問題は、管理者ページ(ホームページなど)から離れてクリックし、[投稿]ボタンをクリックすると、管理者に再ルーティングされ、ログインしていることを認識しますが、ユーザーのデータは利用できなくなります。以前は、ログインコンポーネントから、ユーザーのデータはにありましたthis.props.location.state.me
。
2つの異なるコンポーネントから管理者にルーティングしようとしているので、行き詰まりました。これまでに行ったことがありません。さらに、認証設定に欠けている解決策があるように感じます。
その他のアイデア:
ユーザーのデータが渡されたときに、条件付きで管理者に状態を設定する必要がありますか?
認証トークンを使用する場合と同じように、ブラウザのローカルストレージにデータを保存する必要がありますか?
Adminで状態を設定してデータをフェッチしようとしましたが、componentDidMount
再レンダリングされなかったため、使用するために読み取りましたcomponentWillReceiveProps
が、非推奨になり、に置き換えられていgetDerivedStateFromProps
ます。それを理解できませんでした。
login.jsx
import React, { Component, Fragment } from 'react';
import * as userService from '../../services/user';
import { Redirect } from 'react-router-dom';
import IndeterminateProgress from '../utilities/indeterminateprogress';
import Nav from '../home/nav';
class Login extends Component {
constructor(props) {
super(props);
this.state = {
redirectToReferrer: false,
email: '',
password: '',
feedbackMessage: '',
checkingLogin: true,
me: ''
};
}
componentDidMount() {
userService.checkLogin()
.then((loggedIn) => {
if (loggedIn) {
this.setState({ redirectToReferrer: true, checkingLogin: false });
} else {
this.setState({ checkingLogin: false });
}
});
}
login(e) {
e.preventDefault();
userService.login(this.state.email, this.state.password)
.then((meData) => {
this.setState({ redirectToReferrer: true, me: meData })
})
.catch((err) => {
if (err.message) {
this.setState({ feedbackMessage: err.message });
}
});
}
handleEmailChange(value) {
this.setState({ email: value });
}
handlePasswordChange(value) {
this.setState({ password: value });
}
render() {
const { from } = this.props.location.state || { from: { pathname: '/admin', state: { ...this.state } } };
const { redirectToReferrer, checkingLogin } = this.state;
if (checkingLogin) {
return <IndeterminateProgress message="Checking Login Status..." />;
}
if (redirectToReferrer) {
return (
<Redirect to={from} />
);
}
return (
<Fragment>
<Nav />
<h2 className="heading center">Login to continue</h2>
<form className="center" onSubmit={(e) => this.login(e)}>
<div className="form-group">
<input
placeholder="Email"
id="email"
className="col-3"
type="email"
onChange={(e) => this.handleEmailChange(e.target.value)}
required
/>
</div>
<div className="form-group">
<input
placeholder="Password"
id="password"
className="col-3"
type="password"
onChange={(e) => this.handlePasswordChange(e.target.value)}
required
/>
</div>
{this.state.feedbackMessage ? (
<p>{this.state.feedbackMessage}</p>
) : null}
<input type="submit" value="Login" className="btn btn-info btn-sm" />
</form>
</Fragment>
);
}
}
export { Login };
admin.jsx
import React, { Component } from 'react';
import Nav from '../home/nav';
import AdminBlogContainer from './adminblogcontainer'
import { BrowserRouter as Router, Link } from 'react-router-dom';
const Admin = (props) => {
return (
<div className="flexcol center">
<Nav />
<h1 className="heading">Your Blog Posts</h1>
<AdminBlogContainer {...props.location.state.me} />
<Link to={{
pathname: '/write',
state: { ...props.location.state.me }
}}
className="btn btn-outline-secondary mt-4"
>Create a New Blog Post</Link>
</div>
)
}
export { Admin };
privateroute.jsx
import React from 'react';
import { Route, Redirect } from 'react-router-dom';
import { isLoggedIn } from '../../services/user';
const PrivateRoute = (props) => {
const Component = props.component;
const propsToPass = Object.assign({}, props);
delete propsToPass.component;
return (
<Route {...propsToPass} render={props => (
isLoggedIn() ? (
<Component {...props} />
) : (
<Redirect to={{
pathname: '/login',
state: { from: props.location }
}} />
)
)} />
);
};
export { PrivateRoute }
authbutton.jsx
import React from 'react';
import { Link } from 'react-router-dom';
import { isLoggedIn } from '../../services/user';
const AuthButton = (props) => {
if (isLoggedIn()) {
return (
<div>
<Link className="btn btn-info m-1" to="/logout">Logout</Link>
<Link className='btn btn-info m-1' to={{
pathname: '/admin',
// state: { ...this.state }
}}
>My Posts</Link>
</div>
);
} else {
return (
<div>
<Link className="btn btn-info m-1" to="/login">Login</Link>
<Link className="btn btn-info m-1" to="/register">Register</Link>
</div>
)
}
};
export { AuthButton };
これが店舗づくりの理由のひとつです。これは、アプリケーション内のどこからでもアクセスできるグローバルオブジェクトと考えてください。
私は個人的にmobx / mobx-react(簡単で魔法のように物事を行う)を使用しましたが、reduxもあります
mobxを使用すると、次のようなことができます。
グローバルストア
// /stores/authentication.js
class AuthenticationStore {
user = {};
//authentication logic here
}
const authenticationStore = new AuthenticationStore();
export default authenticationStore;
ルートアプリコンポーネント
// /app.js
import authenticationStore from './stores/authentication';
import { Provider } from 'mobx-react';
export default class App extends Component {
render(){
return (
<Provider authenticationStore={authenticationStore}>
<BrowserRouter>
<SomeComponent/>
</BrowserRouter>
<Provider>);
}
}
一部のコンポーネント。
// /components/some.component.js
@inject('authenticationStore')
class SomeComponent extends Component {
render(){
const {authenticationStore} = this.props;
const {user} = authenticationStore;
render(
<div>${user.name}</div>
)
}
}
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加