Next.jsのSSRでredux(next-redux-wrapper)を使う
20775 ワード
背景
Next.jsでSSRサーバ側レンダリングで特定のページを正しくレンダリングしてクライアントに送信したいと思います.
そのため、以下の2点を実現しなければならない.
ソリューション
next-redux-wrapperを使用してgetServerSidePropsのパッケージを作成する
- https://github.com/Tinkerbell-Green/need-compliments/tree/develop
getServerSidePropsストレージの使用
type Options = {
actionType: DataSagaActionType
key: string
}
export const waitDuringLoading = async (store: Store<RootState, AnyAction>, {actionType, key}: Options) => {
while (true){
await (async () => new Promise(resolve => setTimeout(resolve, 100)))()
const isLoading = store.getState().data[actionType][key].status === DataSagaStatus.LOADING
if (!isLoading) break;
}
}
import {waitDuringLoading} from // ...
// ...
export const getServerSideProps = wrapper.getServerSideProps(store => async ({req, res, ...etc}) => {
const GET_PUBLIC_TASKS_KEY = ""
const GET_GOALS_BY_IDS_KEY = ""
// 액션 디스패치 하기
store.dispatch(dataActionCreators[DataActionType.GET_PUBLIC_TASKS]({
author: undefined,
key: GET_PUBLIC_TASKS_KEY,
startTime: new Date("1999-11-11"),
endTime: new Date("2222-11-11"),
}))
// 데이터 fetch 완료될때까지 기다리기
await waitDuringLoading(store, {actionType: DataActionType.GET_PUBLIC_TASKS, key: GET_PUBLIC_TASKS_KEY})
// state 에서 값 읽기
const tasksGoal = store.getState().data[DataActionType.GET_PUBLIC_TASKS][GET_PUBLIC_TASKS_KEY].data?.map(item => item.goal)
// ...
return ({
props: {}
})
});
クライアント・ステータスとサーバ・ステータスのマージ
getStaticProps
またはgetServerSideProps
を含むページに初期接続または移動する場合、また、
import merge, {Options as MergeOptions} from "deepmerge"
import {HYDRATE} from "next-redux-wrapper";
import {combineReducers} from "redux";
import {dataReducer, State as DataState, initialState as dataInitialState} from "./data";
import {navigationReducer, State as NavigationState, initialState as navigationInitialState} from "./navigation";
const combinedReducer = combineReducers({
data: dataReducer,
navigation: navigationReducer,
});
export type RootState = {
data: DataState;
navigation: NavigationState;
}
const initialRootState: RootState = {
data: dataInitialState,
navigation: navigationInitialState
}
const arrayMerge: MergeOptions["arrayMerge"] = (previousArray, incomingArray, options) => {
const resultArray: typeof previousArray = [...previousArray]
incomingArray.forEach((incomingItem) => {
const prevItemIndex = previousArray.findIndex(previousItem => previousItem.id === incomingItem.id)
if (prevItemIndex !== -1){
resultArray[prevItemIndex] = merge(resultArray[prevItemIndex], incomingItem, options)
}
else {
resultArray.push(incomingItem)
}
})
return resultArray
}
const rootReducer = (previousClientState = initialRootState, action: any) => {
if (action.type === HYDRATE) {
const incomingServerState = action.payload as RootState
const nextState: RootState = {
navigation: previousClientState.navigation,
data: merge(previousClientState.data, incomingServerState.data, {arrayMerge})
}
return nextState;
} else {
return combinedReducer(previousClientState, action);
}
};
export default rootReducer;
レンダリング効果が良好で、クライアントに転送されていることを確認します。
フォント
Reference
この問題について(Next.jsのSSRでredux(next-redux-wrapper)を使う), 我々は、より多くの情報をここで見つけました https://velog.io/@vltea/Next.js-의-SSR-에서-redux-사용하기-next-redux-wrapperテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol