1

请参阅下面的编辑。

我在我的项目中遇到了重置密码问题。我可以向用户发送一封电子邮件,其中包含用于重置密码的链接,其中包含哈希令牌和用户的 ID。

99% 的代码已经完成(后端和前端),唯一的问题是我无法在客户端获取哈希令牌和 id 以调用正确的 API 端点,因此向用户显示用于重置密码的表单,并具有检查令牌、到期日期等的逻辑。

我没有使用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 页面。

如何在客户端获取这些参数?

编辑:

所以现在我next/router按照建议使用。

首先,我注意到如果令牌被/内部散列,next/router则无法读取令牌,它会给我一个 404 页面(可能是因为它认为有超过 2 个参数?)。我试图在/没有成功的情况下调整路线。

出于调试目的,我reset-password-form/[resetToken]/[userId].js进入 pages 文件夹如下所示:

const resetPasswordPage = () => {
    const router = useRouter();

    return (
      <>
        <p>user id: {router.query.userId}</p>
        <p>token: {router.query.resetToken}</p>
      </>
    )
}

结果,这给了我哈希令牌(仅当它在没有/内部的情况下生成,否则我将得到一个 404 页面)和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

如果我从ResetPasswordPage组件中删除其他 2 个子级,则我想要的页面会被呈现(同样,仅当生成的令牌没有 a 时/)。有什么方法可以渲染其他 2 个孩子(我在 3 个组件之间确实有 <> </> 标签)?这些对于页面工作很重要(它们显示导航链接和错误/成功消息)。

我怎样才能避免这样的事实,即如果令牌与 a 进行哈希处理/,用户将获得 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

3

所以为了解决这个问题,我做了以下事情:

将文件 reset-password-form.js 重命名为 pages 文件夹,如“reset-password-form/[resetToken]/[userId].js”。

reset-password-form/[resetToken]/[userId].js 看起来像这样:

import React from 'react';
import { useRouter } from 'next/router';
import ResetPasswordPage from '../../../components/ResetPasswordPage';

const resetPasswordPage = () => {

const router = useRouter();

return (

    <ResetPasswordPage userId={router.query.userId} resetToken={router.query.resetToken} />

)

}

export default resetPasswordPage;

在 ResetPasswordPage 中,我通过这样的道具获取所需的参数:

resetToken = this.props.resetToken;
userId = this.props.userId;

对于令牌内的 / 您需要对令牌 encodeURIComponent 和 decodeURIComponent 进行编码/解码

于 2021-04-18T12:19:29.240 回答
1

Tms给我发了这个链接,他说你有这个问题。我不是专业人士,但尝试从 Route 组件中删除“精确”。由于它是一条动态路径,因此可能是触发问题的原因。

我不太记得了,但你可能也不需要自闭<ResetPasswordPage /> 。您已经在路线中通过了它。(我想我遇到了类似的问题)

于 2021-04-16T20:17:36.373 回答
0

我正在回答您关于您的问题的/问题,因为您在一篇文章中有多个编辑和多个问题。

您可以使用 encodeURIComponent 对包含“/”的令牌进行编码。

const token = `token1with/init`


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

您应该在使用电子邮件发送之前对令牌进行编码。

于 2021-04-18T12:55:53.140 回答