You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Next.js v12使用next-redux-wrapper时Link跳转后state被重置问题

问题根因

你遇到的重复请求和状态重置问题核心来自两个错误:

  1. Next.js 服务端与客户端 Redux store 完全隔离:getServerSideProps 每次运行(包括首次访问、客户端导航跳转)都会在服务端创建全新的 Redux store,你在其中写的 if(state.address.id === null) 判断永远返回 true,所以每次跳转都会触发服务端拉取数据。
  2. getServerSideProps 逻辑错误:你只在 else 分支返回了 props,进入拉取数据的 if 分支后没有任何返回值,会导致 Next.js 拿到异常的返回结果,状态同步出错。

而你的 transaction 切片能正常持久化,是因为它的数据拉取逻辑在客户端执行,服务端 store 中永远没有 transaction 数据,HYDRATE 时不会覆盖客户端已有的状态。

修复方案

1. 修复 getServerSideProps 逻辑

删除无效的服务端状态判断,无论分支都统一返回 props:

export const getServerSideProps = wrapper.getServerSideProps(
  (store) => async (context) => {
    // 服务端每次都是全新 store,直接拉取当前地址对应数据即可
    await store.dispatch(getWalletDetails(context.params.address));
    return {
      props: {
        addressDetails: store.getState().address,
      }
    }
  }
);

2. 调整 HYDRATE 逻辑避免覆盖有效状态

增加地址一致性判断,只有当前客户端存储的地址和服务端返回的地址一致时,才保留客户端状态,否则更新为新地址的数据:

const rootReducer = (state, action) => {
  if (action.type === HYDRATE) {
    const nextState = {
      ...state,
      ...action.payload,
    };
    
    if (state.address?.id && state.address.id === action.payload.address?.id) {
      // 同一个地址,保留客户端已有的状态避免重复请求
      nextState.address = state.address;
    } else {
      // 不同地址,用服务端返回的新数据
      nextState.address = action.payload.address;
    }
    return nextState;
  } else {
    return combinedReducer(state, action);
  }
};

3. 可选:客户端拉取兜底(推荐)

如果你的页面不需要强 SEO 需求,更推荐把数据拉取逻辑移到客户端,用 useEffect 判断是否需要拉取,彻底避免服务端重复请求:

import { useRouter } from 'next/router'
import { useEffect } from 'react'
import { useDispatch, useSelector } from 'react-redux'

function Address(props) {
  const router = useRouter()
  const currentAddress = router.query.address
  const dispatch = useDispatch()
  const storedAddress = useSelector(state => state.address)

  useEffect(() => {
    // 只有当前存储的地址和路由地址不一致时才发起请求
    if (storedAddress.id !== currentAddress) {
      dispatch(getWalletDetails(currentAddress))
    }
  }, [currentAddress, storedAddress.id, dispatch])

  // 原有组件渲染逻辑不变
  return (
    <Fragment>
      <Head>
        <title>RVN</title>
        <meta name="description" content="RVN Address" />
      </Head>
      <AddressDetails address={storedAddress}></AddressDetails>
      <AddressTransactions
        transactions={storedAddress.last_txs}
        address={storedAddress.address}
      ></AddressTransactions>
    </Fragment>
  );
}

这种方案下你甚至可以删除 getServerSideProps 里的拉取逻辑,进一步减少服务端压力。

内容的提问来源于stack exchange,提问作者James Gagne

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 07:24:00