Skip to content

Commit d713188

Browse files
committed
fix($misc): fix HMR, remove onBefore from server, dont call both flushing techniques simultaneously
1 parent 5cf7230 commit d713188

File tree

5 files changed

+24
-25
lines changed

5 files changed

+24
-25
lines changed

README.md

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,7 @@ MyUniversalComponent.doSomething()
245245
246246
- `isLoading: boolean`
247247
- `error: new Error`
248-
- `onBefore`: `({ isMount, isSync, isServer }) => doSomething(isMount, isSync, isServer)`
248+
- `onBefore`: `({ isMount, isSync }) => doSomething(isMount, isSync)`
249249
- `onAfter`: `({ isMount, isSync, isServer }, Component) => doSomething(Component, isMount, etc)`
250250
251251
### `isLoading` + `error`:
@@ -280,9 +280,9 @@ export default graphql(gql`
280280
281281
### `onBefore` + `onAfter`:
282282
283-
`onBefore/After` are callbacks called before and after the wrapped component changes. It's also called on `componentWillMount` on both the client and server. If you chose to use it on the server, make sure the client renders the same thing on first load or you will have checksum mismatches.
283+
`onBefore/After` are callbacks called before and after the wrapped component changes. They are also called on `componentWillMount`. However `onBefore` is never called on the server since both callbacks would always render back to back synchronously. If you chose to use `onAfter` on the server, make sure the client renders the same thing on first load or you will have checksum mismatches.
284284
285-
It's primary use case is for triggering *loading* state **outside** of the component *on the client during child component transitions*. You can use its `info` argument and keys like `info.isSync` to determine what you want to do. Here's an example:
285+
The primary use case for these callbacks is for triggering *loading* state **outside** of the component *on the client during child component transitions*. You can use its `info` argument and keys like `info.isSync` to determine what you want to do. Here's an example:
286286
287287
```js
288288
const UniversalComponent = univesal(props => import(`./props.page`))
@@ -294,7 +294,7 @@ const MyComponent = ({ dispatch, isLoading }) =>
294294
<UniversalComponent
295295
page={props.page}
296296
onBefore={({ isSync }) => !isSync && dispatch({ type: 'LOADING', true })}
297-
onAfter={({ isSync }) => !isSync && dispatch({ type: 'LOADING', false })}
297+
onAfter={({ isSync }, Component) => !isSync && dispatch({ type: 'LOADING', false })}
298298
/>
299299
</div>
300300
```
@@ -303,6 +303,8 @@ Each callback is passed an `info` argument containing these keys:
303303
304304
- `isMount` *(whether the component just mounted)*
305305
- `isSync` *(whether the imported component is already available from previous usage and required synchronsouly)*
306+
307+
**`onAfter` only:**
306308
- `isServer` *(very rarely will you want to do stuff on the server; note: server will always be sync)*
307309
308310
`onAfter` is also passed a second argument containing the imported `Component`, which you can use to do things like call its static methods.

__tests__/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -516,7 +516,7 @@ describe('SSR flushing: flushModuleIds() + flushChunkNames()', () => {
516516
expect(chunkNames).toEqual(['component', 'component3'])
517517
})
518518

519-
it('webpack: dynamic require (babel-plugin', async () => {
519+
it('webpack: dynamic require (babel-plugin)', async () => {
520520
global.__webpack_require__ = path => __webpack_modules__[path]
521521

522522
// modules stored by paths instead of IDs (replicates babel implementation)

src/flowTypes.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,9 +90,10 @@ export type Ids = Array<string>
9090
// RUC
9191
export type State = { error?: any, Component?: ?any }
9292

93-
type Info = { isMount: boolean, isSync: boolean, isServer: boolean }
94-
type OnBefore = Info => void
95-
type OnAfter = (Info, any) => void
93+
type OnBeforeInfo = { isMount: boolean, isSync: boolean }
94+
type OnAfterInfo = { isMount: boolean, isSync: boolean, isServer: boolean }
95+
type OnBefore = OnBeforeInfo => void
96+
type OnAfter = (OnAfterInfo, any) => void
9697

9798
export type Props = {
9899
error?: ?any,

src/index.js

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ export default function universal<Props: Props>(
7474
addModule(this.props) // record the module for SSR flushing :)
7575

7676
if (Component || isServer) {
77-
this.handleBefore(true, true, isServer)
77+
if (!isServer) this.handleBefore(true, true)
7878
this.update({ Component }, true, true, isServer)
7979
return
8080
}
@@ -96,7 +96,7 @@ export default function universal<Props: Props>(
9696
this.props
9797
)
9898

99-
if (shouldUpdate(nextProps, this.props) || isHMR()) {
99+
if (shouldUpdate(nextProps, this.props)) {
100100
const Component = requireSync(nextProps)
101101
this.handleBefore(false, !!Component)
102102

@@ -114,6 +114,9 @@ export default function universal<Props: Props>(
114114

115115
this.update(state, false, true)
116116
}
117+
else if (isHMR()) {
118+
requireSync(nextProps) // just needs to be required again to complete HMR
119+
}
117120
}
118121
}
119122

@@ -150,14 +153,10 @@ export default function universal<Props: Props>(
150153
this.handleAfter(state, isMount, isSync, isServer)
151154
}
152155

153-
handleBefore(
154-
isMount: boolean,
155-
isSync: boolean,
156-
isServer?: boolean = false
157-
) {
156+
handleBefore(isMount: boolean, isSync: boolean) {
158157
if (typeof this.props.onBefore === 'function') {
159158
const onBefore = this.props.onBefore
160-
const info = { isMount, isSync, isServer }
159+
const info = { isMount, isSync }
161160
onBefore(info)
162161
}
163162
}

src/requireUniversalModule.js

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,12 @@ export default function requireUniversalModule<Props: Props>(
119119

120120
const addModule = (props: Object): void => {
121121
if (isServer) {
122+
if (chunkName) {
123+
const name = callForString(chunkName, props)
124+
if (name) CHUNK_NAMES.add(name)
125+
if (!IS_TEST) return // makes tests way smaller to run both kinds
126+
}
127+
122128
if (isWebpack()) {
123129
const weakId = callForString(resolve, props)
124130
if (weakId) MODULE_IDS.add(weakId)
@@ -127,15 +133,6 @@ export default function requireUniversalModule<Props: Props>(
127133
const modulePath = callForString(path, props)
128134
if (modulePath) MODULE_IDS.add(modulePath)
129135
}
130-
131-
// just fill both sets so `flushModuleIds` continues to work,
132-
// even if you decided to start providing chunk names. It's
133-
// a small array of 3-20 chunk names on average anyway. Users
134-
// can flush/clear both sets if they feel they need to.
135-
if (chunkName) {
136-
const name = callForString(chunkName, props)
137-
if (name) CHUNK_NAMES.add(name)
138-
}
139136
}
140137
}
141138

0 commit comments

Comments
 (0)