使用 Link 导航时,具有 next-redux-wrapper 状态的 Next.js 将重置为初始值

问题描述 投票:0回答:2

Next.js v12.0

next-redux-包装器。

每当我使用适当的 next/link 元素离开页面然后再次返回(使用另一个链接 el)时,状态都会重置为初始值,因此会执行另一个获取。奇怪的是,我以相同的方式设置了另一个“事务”切片,只不过它包含一组事务对象,并且其中一个工作得很好(导航离开并返回,并且数据在持续存在时不会重新获取)商店中)代码如下,如有任何建议,我们将不胜感激。

store.js

import { HYDRATE, createWrapper } from "next-redux-wrapper";
import thunkMiddleware from "redux-thunk";
import address from "./address/reducer";
import transactions from "./transaction/reducer";

const bindMiddleware = (middleware) => {
  if (process.env.NODE_ENV !== "production") {
    const { composeWithDevTools } = require("redux-devtools-extension");
    return composeWithDevTools(applyMiddleware(...middleware));
  }
  return applyMiddleware(...middleware);
};

const combinedReducer = combineReducers({
  transactions,
  address,
});

const rootReducer = (state, action) => {
  if (action.type === HYDRATE) {
    const nextState = {
      ...state, // use previous state
      ...action.payload, // apply delta from hydration
    };
    
    if (state.address.id){
      nextState.address = state.address;
    }
    return nextState;
  } else {
    return combinedReducer(state, action);
  }
};


const initStore = () => {
  return createStore(rootReducer, bindMiddleware([thunkMiddleware]));
};
export const wrapper = createWrapper(initStore);

地址/reducer.js


const addressInitialState = {
  id: null,
  timestamp: null,
  address: null,
  balance: null,
  received: null,
  sent: null,
  groupid: null,
  last_txs: []
};

export default function reducer(state = addressInitialState, action) {
  switch (action.type) {
    case addressActionTypes.GET_WALLET_DETAILS:
      return {id: action.payload.address, ...action.payload};
    default:
      return state;
  }
}

地址/action.js

export const addressActionTypes = {
  GET_WALLET_DETAILS: "GET_WALLET_DETAILS",
};

export const getWalletDetails = (address) => {
  return async (dispatch) => {
    const fetchData = async () => {
      const response = await fetch(
        `https:someapi.com/api/getaddress/?address=${address}`
      );
      if (!response.ok) {
        throw new Error("Could not fetch address data!");
      }

      const data = await response.json();
      console.log('req sent');
      return data;
    };
    try {
      const addressData = await fetchData();
      dispatch({
        type: addressActionTypes.GET_WALLET_DETAILS,
        payload: addressData,
      });
    } catch (err) {
      console.log(err);
    }
  };
};

页面/[地址].js

import { Fragment } from "react";
import Head from "next/head";
import AddressDetails from "../../../components/crypto/rvn/AddressDetails";
import AddressTransactions from "../../../components/crypto/rvn/AddressTransactions";
import { connect } from "react-redux";
import { getWalletDetails } from "../../../store/address/action";
import { wrapper } from "../../../store/store";

function Address(props) {
  return (
    <Fragment>
      <Head>
        <title>RVN</title>
        <meta name="description" content="RVN Address" />
      </Head>
      <AddressDetails address={props.addressDetails}></AddressDetails>
      <AddressTransactions
        transactions={props.addressDetails["last_txs"]}
        address={props.addressDetails.address}
      ></AddressTransactions>
    </Fragment>
  );
}

export const getServerSideProps = wrapper.getServerSideProps(
  (store) => async (context) => {
    const state = store.getState();
    if(state.address.id === null) {
      await store.dispatch(getWalletDetails(context.params.address));
    }
    else{
      return{
        props: {
          addressDetails: state.address,
        }
      }
    }
  }
);


const mapStateToProps = (state) => ({
  addressDetails: state.address,
});
export default connect(mapStateToProps, null)(Address);
reactjs redux next.js next-redux-wrapper
2个回答
4
投票

通过转换这个解决了这个问题

const initStore = () => {
  return createStore(rootReducer, bindMiddleware([thunkMiddleware]));
};

在 store.js 直接来自 https://github.com/vercel/next.js/tree/canary/examples/with-redux-thunk

到此

const store = createStore(rootReducer, bindMiddleware([thunkMiddleware]));

const initStore = () => {
  return store
};

因此每次使用包装器时它不会重新初始化存储

这更符合文档 https://github.com/kirill-konshin/next-redux-wrapper


0
投票
    // Adding ref has resolved my issue ....
    "use client";
    import { ReactNode, useRef } from "react";
    import { Provider } from "react-redux";
    import { AppStore, makeStore } from "../rtk/store";
    import { ToastContainer } from "react-toastify";
    import { Wrapper } from "@containers";
    import "react-toastify/dist/ReactToastify.css";
    import { ThemeProviderWrapper } from "app/theme/ThemeProviderWrapper";
    
    export function ClientOnlyProvider({ children }: { children: ReactNode }) {
      const storeRef = useRef<AppStore>();
      if (!storeRef.current) {
        // Create the store instance the first time this renders
    enter code here
        // Call your store here to resolve reset issue
        storeRef.current = makeStore();
      }
    
      return (
        <ThemeProviderWrapper>
          <Provider store={storeRef.current}>
            <ToastContainer />
            <Wrapper>{children}</Wrapper>
          </Provider>
        </ThemeProviderWrapper>
      );
    }
© www.soinside.com 2019 - 2024. All rights reserved.