diff --git a/__test__/SSR/index.spec.ts b/__test__/SSR/index.spec.ts
new file mode 100644
index 0000000..d146056
--- /dev/null
+++ b/__test__/SSR/index.spec.ts
@@ -0,0 +1,29 @@
+///
+import '@testing-library/react/cleanup-after-each'
+import { Model } from '../../src'
+import { SSRCounter } from '..'
+
+describe('asyncState', () => {
+ test('return default initial state from asyncState', async () => {
+ const { getInitialState } = Model({
+ WrappedSSRCounter: Model(SSRCounter),
+ SSRCounter
+ })
+ const initialModels = await getInitialState(undefined, { isServer: true })
+ // const state = getState('AsyncCounter')
+ expect(initialModels['SSRCounter'].count).toBe(1)
+ expect(initialModels['SSRCounter'].clientKey).toBe(undefined)
+ expect(initialModels['WrappedSSRCounter'].count).toBe(1)
+ expect(initialModels['WrappedSSRCounter'].clientKey).toBe(undefined)
+
+ // Simulate Client Side
+ const { getState } = Model(
+ { WrappedSSRCounter: Model(SSRCounter), SSRCounter },
+ initialModels
+ )
+ expect(initialModels['SSRCounter'].count).toBe(1)
+ expect(initialModels['WrappedSSRCounter'].count).toBe(1)
+ expect(getState('SSRCounter').clientKey).toBe('unused')
+ expect(getState('WrappedSSRCounter').clientKey).toBe('unused')
+ })
+})
diff --git a/__test__/index.d.ts b/__test__/index.d.ts
index a42490d..d165419 100644
--- a/__test__/index.d.ts
+++ b/__test__/index.d.ts
@@ -2,6 +2,11 @@ type CounterState = {
count: number
}
+type SSRCounterState = {
+ count: number
+ clientKey: string
+}
+
type ExtState = {
name: string
}
diff --git a/__test__/index.ts b/__test__/index.ts
index a260a0d..b982da5 100644
--- a/__test__/index.ts
+++ b/__test__/index.ts
@@ -113,6 +113,20 @@ export const AsyncCounter: ModelType = {
state: { count: 0 }
}
+export const SSRCounter: ModelType = {
+ actions: {
+ increment: params => {
+ return state => {
+ state.count += params
+ }
+ }
+ },
+ asyncState: async (context: { count?: number }) => ({
+ count: context ? context.count || 1 : 1
+ }),
+ state: { count: 0, clientKey: 'unused' }
+}
+
export const AsyncNull: ModelType = {
actions: {
increment: params => {
diff --git a/package.json b/package.json
index cca7261..8e09448 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "react-model",
- "version": "3.0.4",
+ "version": "3.1.0",
"description": "The State management library for React",
"main": "./dist/react-model.js",
"umd:main": "./dist/react-model.umd.js",
diff --git a/src/helper.ts b/src/helper.ts
index 7105183..0c55c53 100644
--- a/src/helper.ts
+++ b/src/helper.ts
@@ -80,7 +80,11 @@ const timeout = (ms: number, data: T): Promise =>
}, ms)
)
-const getInitialState = async (context?: T) => {
+const getInitialState = async (
+ context?: T,
+ config?: { isServer?: boolean }
+) => {
+ const ServerState: { [name: string]: any } = { __FROM_SERVER__: true }
await Promise.all(
Object.keys(Global.State).map(async modelName => {
if (
@@ -91,14 +95,18 @@ const getInitialState = async (context?: T) => {
) {
const asyncGetter = Global.AsyncState[modelName]
const asyncState = asyncGetter ? await asyncGetter(context) : {}
- Global.State[modelName] = {
- ...Global.State[modelName],
- ...asyncState
+ if (config && config.isServer) {
+ ServerState[modelName] = asyncState
+ } else {
+ Global.State[modelName] = {
+ ...Global.State[modelName],
+ ...asyncState
+ }
}
}
})
)
- return Global.State
+ return config && config.isServer ? ServerState : Global.State
}
const getCache = (modelName: string, actionName: string) => {
diff --git a/src/index.d.ts b/src/index.d.ts
index 7fbb3df..87f4417 100644
--- a/src/index.d.ts
+++ b/src/index.d.ts
@@ -142,7 +142,8 @@ interface APIs {
? M[K]['actions']
: unknown
getInitialState: (
- context?: T | undefined
+ context?: T | undefined,
+ config?: { isServer: boolean }
) => Promise<{
[modelName: string]: any
}>
diff --git a/src/index.tsx b/src/index.tsx
index 706c4bc..4bb85d7 100644
--- a/src/index.tsx
+++ b/src/index.tsx
@@ -76,7 +76,7 @@ function Model(
useStore: errorFn([{}, {}])
} as any
}
- if (initialState) {
+ if (initialState && !initialState.__FROM_SERVER__) {
Global.State = initialState || {}
}
extContext && (Global.Context['__global'] = extContext)
@@ -89,7 +89,9 @@ function Model(
return
}
if (!isAPI(model)) {
- if (!Global.State[name]) {
+ if (initialState && initialState.__FROM_SERVER__) {
+ Global.State[name] = { ...model.state, ...initialState[name] }
+ } else if (!Global.State[name]) {
Global.State[name] = model.state
}
if (model.middlewares) {
@@ -102,6 +104,12 @@ function Model(
if (!Global.State[name] || !initialState) {
Global.State[name] = Global.State[model.__id]
}
+ if (initialState && initialState.__FROM_SERVER__) {
+ Global.State[name] = {
+ ...Global.State[model.__id],
+ ...initialState[name]
+ }
+ }
Global.Actions[name] = Global.Actions[model.__id]
Global.AsyncState[name] = Global.AsyncState[model.__id]
Global.Middlewares[name] = Global.Middlewares[model.__id]