Nextjs项目鉴权,数据水合,接口token存储问题相关问题探讨

705 阅读2分钟

先说我遇到的问题

  • 1.在Nextjs中怎么样把服务端数据和客户端数据整合在一起保持一致性?
  • 2.看nextjs github官方示例接口请求都是放在pages/api目录下面,这个是推荐使用吗?为什么要这样呢?
  • 3.我使用nuxtjs较多,nuxtjs中存在plugins概念,接口都是通过plugins封装的方式,制作一个统一的请求管道,我们在这个管道中处理通用逻辑,如果是在nextjs中要如何处理这个通用逻辑
  • 先晒出我的nextjs在用的水合方案
  • store/user.ts
import { configureStore, createSlice } from '@reduxjs/toolkit';
import { createWrapper, HYDRATE } from 'next-redux-wrapper';

export const userSlice = createSlice({
  name: 'userData',
  initialState: {},
  reducers: {
    setUserData(state, action) {
      return action.payload;
    },
  },
  extraReducers: {
    [HYDRATE]: (state, action) => {
      return {
        ...state,
        ...action.payload.userData,
      };
    },
  },
});

const makeStore = () =>
  configureStore({
    reducer: {
      [userSlice.name]: userSlice.reducer,
    },
    devTools: true,
  });

export type AppStore = ReturnType<typeof makeStore>;
export type AppState = ReturnType<AppStore['getState']>;
export const wrapper = createWrapper<AppStore>(makeStore);
export const { setUserData } = userSlice.actions;
export const selectUser = () => (state: AppState) => state?.[userSlice.name];

store/systemData.ts

import { configureStore, createSlice } from '@reduxjs/toolkit';
import { createWrapper, HYDRATE } from 'next-redux-wrapper';

export const systemSlice = createSlice({
  name: 'systemData',
  initialState: {},
  reducers: {
    setSystemData(state, action) {
      return action.payload;
    },
  },
  extraReducers: {
    [HYDRATE]: (state, action) => {
      return {
        ...state,
        ...action.payload.systemData,
      };
    },
  },
});

const makeStore = () =>
  configureStore({
    reducer: {
      [systemSlice.name]: systemSlice.reducer,
    },
    devTools: true,
  });

export type AppStore = ReturnType<typeof makeStore>;
export type AppState = ReturnType<AppStore['getState']>;
export const wrapper = createWrapper<AppStore>(makeStore);

export const { setSystemData } = systemSlice.actions;
export const selectSystem = () => (state: AppState) => state?.[systemSlice.name];

pages/_app.tsx

import React, { FC } from 'react';
import 'styles/globals.css';
import { Provider } from 'react-redux';
import { wrapper, setUserData } from 'store/user';
const MyApp = ({ Component, ...rest }) => {
  const { store, props } = wrapper.useWrappedStore(rest);
  return (
    <Provider store={store}>
      <Component {...rest} />
    </Provider>
  );
};

MyApp.getInitialProps = wrapper.getInitialPageProps((store) => async ({ pathname, req, res }) => {
  store.dispatch(setUserData({ id: 321, name: '直接设置' }));
});
export default MyApp;

pages/page1.tsx

import type { NextPage } from 'next';
import Head from 'next/head';
import styled from 'styled-components';
import { useDispatch } from 'react-redux';
import { useSelector, useStore } from 'react-redux';
import { selectUser, wrapper, setUserData } from 'store/user';

let BoxDiv = styled.div`
  color: green;
  font-size: 20px;
  text-align: center;
  line-height: normal;
`;
const testFn = () => {
  return 3;
};
const Home: NextPage = () => {
  let dispatch = useDispatch();
  const content = useSelector(selectUser());
  return (
    <BoxDiv>
      <Head>
        <title>Create Next App</title>
        <meta name="description" content="Generated by create next app" />
        <link rel="icon" href="/favicon.ico" />
      </Head>
      <div className="title">页面1</div>
      {content.name}
      <button
        onClick={() => {
          dispatch(setUserData({ id: 567, name: '测试' }));
        }}
      >
        修改
      </button>
    </BoxDiv>
  );
};
export const getServerSideProps = wrapper.getServerSideProps((store) => async ({ params, req }) => {
  return {
    props: {
      // id,
    },
  };
});
export default Home;

上述中在_app.tsx中注入前端需要的store数据 然后在页面page1中使用,就是想问一下 其他使用nextjs的大佬也是这样用的吗?