以下の編集を参照してください。
プロジェクトでパスワードのリセットの問題が発生しています。ハッシュ化されたトークンと内部のユーザー ID を使用してパスワードをリセットするためのリンクを記載したメールをユーザーに送信できます。
コードの 99% は既に完了しています (バックエンドとフロントエンド)。唯一のことは、正しい API エンドポイントを呼び出してユーザーに表示するために、ハッシュされたトークンとクライアント側の ID を取得できないことです。パスワードをリセットするためのフォームと、トークン、有効期限などをチェックするロジックがあります。
私は使用しreact-router-dom
ていません (このルートにのみ使用しようとしても、とにかく機能させることはできません)。
基本的に、ユーザーに送信するリンクは次のとおりです。
`http://localhost:3000/reset-password-form/${hashedResetToken}/${user._id}`
私のルートは次のようになります。
router.patch('/reset-password-form/:resetToken/:userId', shopController.resetPasswordPage);
ここで、このような react-router-dom の機能を、次のようにページ フォルダー内の reset-password-form.js ファイルに追加しようとしました。
import React from 'react';
import ResetPasswordPage from '../components/ResetPasswordPage';
import { BrowserRouter as Router, Switch, Route} from 'react-router-dom';
const resetPasswordPage = () => {
return (
<>
<Router>
<Switch>
<Route exact path="/reset-password-form/:resetToken/:userId" component={ResetPasswordPage} />
</Switch>
</Router>
<ResetPasswordPage />
</>
)
}
export default resetPasswordPage;
そして、問題は、必要なパラメーターを取得できないため、正しい API エンドポイントを呼び出すことができないことです。コンポーネントは次のようになります (コンポーネント全体ではなく、数行のコードです)。
fetchData = e => {
e.preventDefault();
const resetToken = this.props.match.params.resetToken;
const userId = this.props.match.params.userId;
fetch(`http://localhost:8090/reset-password-form/${resetToken}/${userId}`, {
そのため、今リンクをクリックすると、404 page not found が表示されます。
クライアント側でこれらのパラメーターを取得するにはどうすればよいですか?
編集:
だから今、私はnext/router
それが提案されたように使用しています。
/
最初に、トークンが内部でハッシュされると、トークンを読み取ることができず、404 ページが表示されることに気付きnext/router
ました (おそらく、2 つ以上のパラメーターがあると考えているためですか?)。なしでルートを調整しようとしました/
が、成功しませんでした。
デバッグの目的でreset-password-form/[resetToken]/[userId].js
、ページ フォルダーに移動すると、次のようになります。
const resetPasswordPage = () => {
const router = useRouter();
return (
<>
<p>user id: {router.query.userId}</p>
<p>token: {router.query.resetToken}</p>
</>
)
}
これにより、結果としてハッシュされたトークン (/
内部なしで生成された場合のみ) とuserId
.
デバッグ後、2つのp
タグを削除しResetPasswordPage
、リターン内でコンポーネントを渡し、必要なパラメーターを小道具として渡し、次のように取得します(ResetPasswordPage
コンポーネント):
fetchData = e => {
e.preventDefault();
const resetToken = this.props.resetToken;
const userId = this.props.userId;
fetch(`http://localhost:8090/reset-password-form/${resetToken}/${userId}`, {
しかし、そうすれば私は得るでしょうError: React.Children.only expected to receive a single React element child
。
コンポーネントから他の 2 つの子を削除すると、ResetPasswordPage
必要なページがレンダリングされます (トークンが なしで生成された場合のみ/
)。他の 2 つの子もレンダリングする方法はありますか (3 つのコンポーネントの間に <> </> タグがあります)。これらはページが機能するために重要です (ナビゲーション リンクとエラー/成功メッセージが表示されます)。
/
トークンが でハッシュされた場合にユーザーが 404 ページを取得するという事実を回避するにはどうすればよいですか?
編集 2.0
コンポーネントの完全なコードResetPasswordPage
:
import React, { Component } from 'react';
import Link from 'next/link';
import Form from '../components/styles/Form';
import Logo from '../components/styles/Logo';
import MessageStyles from '../components/styles/MessageStyles';
class ResetPasswordPage extends Component {
state = {
loading: false,
message: null,
password: '',
confirmPassword: '',
}
handleChange = e => {
this.setState({ [e.target.name]: e.target.value });
}
fetchData = e => {
e.preventDefault();
const resetToken = this.props.resetToken;
const userId = this.props.userId;
fetch(`http://localhost:8090/reset-password-form/${resetToken}/${userId}`, {
method: 'PATCH',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
credentials: 'include',
body: JSON.stringify({
password: this.state.password,
confirmPassword: this.state.confirmPassword,
})
})
.then(res => {
return res.json();
})
.then(resData => {
console.log(resData);
})
.then(() => {
setTimeout(() => {
window.location.replace('/auth/login');
}, 3000);
})
.catch(err => console.log(err))
}
render() {
return (
<>
<Logo> // by removing only the logo component with the link inside I solved the issue of Error: React.Children.only expected to receive a single React element child
<Link href="/shop" />
</Logo>
<MessageStyles><p id="message-test">{this.state.message}</p></MessageStyles>
<Form onSubmit={this.fetchData}>
<fieldset aria-busy={this.state.loading} disabled={this.state.loading}>
<h1>Chang{this.state.loading ? 'ing' : 'e'} Your Password</h1>
<label htmlFor="password">
<input
name="password"
type="password"
onChange={this.handleChange}
value={this.state.password}
className={this.state.password.length < 5 ? 'invalid' : '' }
/>
</label>
<label htmlFor="confirm password">
<input
name="confirmPassword"
type="password"
onChange={this.handleChange}
value={this.state.confirmPassword}
className={this.state.password !== this.state.confirmPassword ? 'invalid' : '' }
/>
</label>
<button>Chang{this.state.loading ? 'ing' : 'e'} Your Password</button>
</fieldset>
</Form>
</>
)
}
}
export default ResetPasswordPage;
したがって、削除するLogo
とMessageStyle
ページがレンダリングされます。