太原网站制作_太原网站建设_太原做网站_秘密武器开发者中心
历史搜索

React Next.js 集成状态管理器和共享Token

游客2025-03-03 15:35:13
目录文章目录
  1. Token 存储
  2. 数据持久化
  3. 状态管理
  4. 集成状态管理器 Redux 及共享 Token 信息
  5. 注意
  6. 总结

React Next.js 集成状态管理器和共享Token 1

剩下代码

pages/login.js

import React, {useState, useEffect} from "react";
import {Form, Input, Button, Checkbox, message, Alert, Typography} from "antd";
import Record from "../../components/layout/record";
import styles from "./index.module.scss";
import {useRouter} from "next/router";
import {useSelector, useDispatch} from 'react-redux'
import {login} from '@/store/slices/auth';
import {wrapper} from '@/store'


const {Text, Link} = Typography;
const layout = {
  labelCol: {span: 24},
  wrapperCol: {span: 24}
};
const Login = props => {
  const dispatch = useDispatch();
  const router = useRouter();
  const [isLoding, setIsLoading] = useState(false);
  const [error, setError] = useState({
    show: false,
    content: ""
  });

  function closeError() {
    setError({
      show: false,
      content: ""
    });
  }

  const onFinish = async ({username, password}) => {
    if (!username) {
      setError({
        show: true,
        content: "请输入用户名"
      });
      return;
    }
    if (!password) {
      setError({
        show: true,
        content: "请输入密码"
      });
      return;
    }
    setIsLoading(true);
    let res = await dispatch(login({
      grant_type: "password",
      username,
      password
    }));
    if (res.payload.errorMsg) {
      message.warning(res.payload.errorMsg);
    } else {
      router.push("/");
    }
    setIsLoading(false);
  };

  function render() {
    return props.isLogin ? (
      <></>
    ) : (
      <div className={styles.container}>
        <div className={styles.content}>
          <div className={styles.card}>
            <div className={styles.cardBody}>
              <div className={styles.error}>{error.show ?
                <Alert message={error.content} type="error" closable afterClose={closeError}/> : null}</div>
              <div className={styles.cardContent}>
                <Form
                  {...layout}
                  name="basic"
                  initialValues={{remember: true}}
                  layout="vertical"
                  onFinish={onFinish}
                  // onFinishFailed={onFinishFailed}
                >
                  <div className={styles.formlabel}>
                    <b>用户名或邮箱</b>
                  </div>
                  <Form.Item name="username">
                    <Input size="large"/>
                  </Form.Item>
                  <div className={styles.formlabel}>
                    <b>密码</b>
                    <Link href="/account/password_reset" target="_blank">
                      忘记密码
                    </Link>
                  </div>
                  <Form.Item name="password">
                    <Input.Password size="large"/>
                  </Form.Item>

                  <Form.Item>
                    <Button type="primary" htmlType="submit" block size="large" className="submit" loading={isLoding}>
                      {isLoding ? "正在登录..." : "登录"}
                    </Button>
                  </Form.Item>
                </Form>
                <div className={styles.newaccount}>
                  首次使用 Seaurl?{" "}
                  <Link href="/join?ref=register" target="_blank">
                    创建一个账号
                  </Link>
                  {/* <a className="login-form-forgot" href="" >
                                    创建一个账号</a> */}
                </div>
              </div>
            </div>

            <div className={styles.recordWrapper}>
              <Record/>
            </div>
          </div>
        </div>
      </div>
    );
  }

  return render();
};

export const getServerSideProps = wrapper.getServerSideProps(store => ({ctx}) => {
  const {isLogin, me} = store.getState().auth;
  if(isLogin){
    return {
      redirect: {
        destination: '/',
        permanent: false,
      },
    }
  }
  return {
    props: {}
  };
});

export default Login;

注意

1、使用了next-redux-wrapper一定要加 HYDRATE,目的是同步服务端和客户端 reducer 数据,否则两个端数据不一致造成冲突。

[HYDRATE]: (state, action) => {
      console.log('HYDRATE', state, action.payload);
      return Object.assign({}, state, {...action.payload.auth});
    },

2、注意next-redux-wrappernext-redux-cookie-wrapper版本。

"next-redux-cookie-wrapper": "^2.0.1",
"next-redux-wrapper": "^7.0.2",

总结

  1. ssr 项目不要用持久化,而是直接从 server 端请求接口拿数据直接渲染,否则失去使用 SSR 的意义了;
  2. Next.js 分为静态渲染和服务端渲染,其实 SSR 项目如果你的项目很小,或者都是静态数据可以考虑直接使用客户端静态方法getStaticProps来渲染。
标签:Next.js

本文是由用户"游客"发布,所有内容的版权归原作者所有。没有经过书面许可,任何单位或个人不得以任何形式复制、转载、引用本网站的内容。否则将追究法律责任。

相关专题