在使用next.js 我们有一部分数据,是需要同步到服务端环境的,在页面到达浏览器之前,redux就应该填充一部分数据
其他框架参考, nuxt.js vuex 某个只在服务端初始化执行的action函数
首先建立仓库文件 store/index.js
- import { combineReducers, createStore } from 'redux';
- import { composeWithDevTools } from 'redux-devtools-extension/developmentOnly';
- import user from './reducers/user'
- import config from './reducers/config'
- import anchor from './reducers/anchor';
- import router from './reducers/router';
- //每个redux已经单独分开,如果在初始化需要单独初始化某个模块的数据,需要这样合并,详情看redux文档
- const combined = (state = {}, action) => {
- return {
- user: user(state?.user, action),
- config: config(state?.config, action),
- router: router(state?.router, action),
- anchor: anchor(state?.anchor, action)
- };
- }
- //这里为了在服务端创建时,初始化一遍redux
- const createNextStore = (init) => createStore(combined, init, composeWithDevTools());
-
- export default createNextStore
建立withRedux 用于结合redux和app
- import createNextStore from "./index";
- import { getUserInfo, getAnchorPage } from '@/service/live';
- import dayJs from 'dayjs';
- import React from 'react'
- const __NEXT_REDUX_STORE = "__NEXT_REDUX_STORE"; //定义个变量用来查看客户端是否存在store
-
- //根据不同场景进行创建或者返回现有store
- function getOrCreateStore (initialState) {
- const isServer = typeof window === "undefined";
- if (isServer) {
- // 服务端
- // 返回新的store
- return createNextStore(initialState);
- }
-
- if (!window[__NEXT_REDUX_STORE]) {
- // console.log('XXX')
- // 是客户端客户端没有store create
- window[__NEXT_REDUX_STORE] = createNextStore(initialState);
- }
- return window[__NEXT_REDUX_STORE];
- }
- const withRedux = (Comp) => {
- // 高阶组件,让每个app都经历高阶组件进行处理集成redux
- return class HocReducerComp extends React.Component {
- constructor(props) {
- super(props);
- this.ReduxStore = getOrCreateStore(props.initialState);
- }
- static async getInitialProps (ctx) {
- let user = {
- }
-
- let anchor = {
- }
- //尝试在服务端先获取用户信息,在注入到客户端
- try {
- //尝试获取用户信息
-
- if (ctx.ctx.req?.cookies['app-access-token']) {
- const code = ctx.ctx.req.cookies['app-access-token'] || ""
- user.info = await getUserInfo({
- headers: {
- "app-access-token": code
- }
- })
- user.info['app_access_token'] = code
- user.info = { ...user?.info, registerDay: dayJs().diff(dayJs(user?.info?.createTime), 'day') || 0, }
- if (user?.info?.roomId) {
- const c = await getAnchorPage({
- headers: {
- "app-access-token": code
- }
- })
- const { host = {}, ...other } = c;
- anchor.anchorInfo = { ...host, ...other }
- }
- }
- } catch (error) {
- console.log(error)
- }
- const MyStore = getOrCreateStore({ anchor, user });
- /* 利用ctx把store传入App,在App中进行store的初始化 */
- ctx.ReduxStore = MyStore;
- let appProps = {};
- if (typeof Comp.getInitialProps === 'function') {
- appProps = await Comp.getInitialProps(ctx);
- }
- // 这里都是在服务端重新注入数据
- return { ...appProps, initialState: MyStore.getState() };
- }
- render () {
- return <Comp {...this.props} ReduxStore={this.ReduxStore} />;
- }
- }
- };
- export default withRedux;
_app.js 合并
- import 'normalize.css';
- import '../styles/main.scss';
- import { Provider } from "react-redux";
- import withRedux from "@/store/withRedux"
- import App from 'next/app'
- function nextApp ({ Component, pageProps, ReduxStore }) {
-
- return (
- <Provider store={ReduxStore}>
- <Component {...pageProps} />
- Provider>
- )
- }
-
- nextApp.getInitialProps = async (ctx) => {
- const appProps = await App.getInitialProps(ctx);
- //ctx.ReduxStore
- return { ...appProps };
- };
-
- export default withRedux(nextApp)