1

以下の編集を参照してください。

プロジェクトでパスワードのリセットの問題が発生しています。ハッシュ化されたトークンと内部のユーザー 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;

したがって、削除するLogoMessageStyleページがレンダリングされます。

4

3 に答える 3

0

/1 つの投稿に複数の編集と複数の質問があるため、問題に関する質問にお答えします。

トークンに「/」が含まれている場合は、encodeURIComponent を使用してトークンをエンコードできます。

const token = `token1with/init`


console.log(`token`, token)
console.log(`encodeUri`, encodeURIComponent(token))

電子メールで送信する前に、トークンをエンコードする必要があります。

于 2021-04-18T12:55:53.140 に答える