Skip to content

Commit

Permalink
feat($release): 2.0 with support for babel-plugin-universal-import
Browse files Browse the repository at this point in the history
  • Loading branch information
faceyspacey committed Jul 26, 2017
1 parent 6f34f3a commit 0311e42
Show file tree
Hide file tree
Showing 9 changed files with 129 additions and 281 deletions.
321 changes: 76 additions & 245 deletions README.md

Large diffs are not rendered by default.

5 changes: 1 addition & 4 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "react-universal-component",
"version": "2.0.1",
"version": "0.0.0-development",
"description": "A higher order component for loading components with promises",
"main": "dist/index.js",
"author": "James FaceySpacey Gillmore <[email protected]> (http://www.faceyspacey.com)",
Expand Down Expand Up @@ -68,9 +68,6 @@
"git add"
]
},
"dependencies": {
"require-universal-module": "^1.2.8"
},
"repository": {
"type": "git",
"url": "https://github.com/faceyspacey/react-universal-component.git"
Expand Down
Binary file added react-router-quote.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 2 additions & 1 deletion src/flowTypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,8 @@ export type Tools = {
requireAsync: RequireAsync,
requireSync: RequireSync,
addModule: AddModule,
shouldUpdate: () => boolean
shouldUpdate: (nextProps: Object, props: Object) => boolean,
asyncOnly: boolean
}

export type Ids = Array<string>
Expand Down
64 changes: 35 additions & 29 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ import { DefaultLoading, DefaultError, isServer, createElement } from './utils'

let hasBabelPlugin = false

// $FlowIgnore
const isHMR = () => module.hot && module.hot.data

export const setHasBabelPlugin = () => {
hasBabelPlugin = true
}
Expand All @@ -35,10 +38,9 @@ export default function universal<Props: Props>(
options.modCache = {}
options.promCache = {}

let Component

return class UniversalComponent extends React.Component<void, Props, *> {
_mounted: boolean
_asyncOnly: boolean

static preload(props: Props) {
props = props || {}
Expand All @@ -49,57 +51,61 @@ export default function universal<Props: Props>(
constructor(props: Props) {
super(props)

const { requireSync } = req(component, options, props)
Component = requireSync(props)
const { requireSync, asyncOnly } = req(component, options, props)
this._asyncOnly = asyncOnly

this.state = {
error: null,
hasComponent: !!Component
Component: requireSync(props)
}
}

componentWillMount() {
this._mounted = true
const { addModule, requireAsync } = req(component, options, this.props)
addModule(this.props) // record the module for SSR flushing :)

if (this.state.Component || isServer) return
this.requireAsync(requireAsync, this.props)
}

componentWillUnmount() {
this._mounted = false
}

componentWillReceiveProps(nextProps: Props) {
if (isDynamic) {
if (isDynamic || this._asyncOnly) {
const { requireSync, requireAsync, shouldUpdate } = req(
component,
options,
nextProps,
this.props
)

if (shouldUpdate()) {
Component = requireSync(nextProps)
// if !Component, a re-render will happen and show <Loading />
if (shouldUpdate(nextProps, this.props) || isHMR()) {
const Component = requireSync(nextProps)

if (!Component) {
return this.requireAsync(requireAsync, nextProps)
}

this.update({ hasComponent: !!Component })
this.update({ Component })
}
}
}

componentWillMount() {
this._mounted = true
const { addModule, requireAsync } = req(component, options, this.props)
addModule(this.props) // record the module for SSR flushing :)

if (this.state.hasComponent || isServer) return
this.requireAsync(requireAsync, this.props)
}

componentWillUnmount() {
this._mounted = false
}

requireAsync(requireAsync: RequireAsync, props: Props) {
// insure `loading` displays even when the component
// changes during componentWillReceiveProps
if (this.state.Component) {
this.update({ Component: null })
}

const time = new Date()

requireAsync(props)
.then((exp: ?any) => {
Component = exp // for HMR updates component must be in closure
const state = { hasComponent: !!Component }
.then((Component: ?any) => {
const state = { Component }

const timeLapsed = new Date() - time
if (timeLapsed < minDelay) {
Expand All @@ -111,14 +117,14 @@ export default function universal<Props: Props>(
.catch(error => this.update({ error }))
}

update = (state: { error?: any, hasComponent?: boolean }) => {
update = (state: { error?: any, Component?: ?any }) => {
if (!this._mounted) return
if (!state.error) state.error = null
this.setState(state)
}

render() {
const { error, hasComponent } = this.state
const { error, Component } = this.state
const { isLoading, error: userError, ...props } = this.props

// user-provided props (e.g. for data-fetching loading):
Expand All @@ -128,7 +134,7 @@ export default function universal<Props: Props>(
else if (userError) {
return createElement(Err, { ...props, error: userError })
}
else if (hasComponent && Component) {
else if (Component) {
// primary usage (for async import loading + errors):
return createElement(Component, props)
}
Expand Down
17 changes: 15 additions & 2 deletions src/requireUniversalModule.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ export default function requireUniversalModule<Props: Props>(

const config = getConfig(isDynamic, universalConfig, options, props)
const { chunkName, path, resolve, load } = config
const asyncOnly = !path && !resolve

const requireSync = (props: Object): ?any => {
let exp = loadFromCache(chunkName, props, modCache)
Expand Down Expand Up @@ -134,7 +135,18 @@ export default function requireUniversalModule<Props: Props>(
}
}

const shouldUpdate = (): boolean => {
const shouldUpdate = (next, prev): boolean => {
if (asyncOnly) {
const cacheKey = callForString(chunkName, next)

const config = getConfig(isDynamic, universalConfig, options, prev)
const prevCacheKey = callForString(config.chunkName, prev)

return cacheKey !== prevCacheKey
}

// below is what the babel-plugin triggers

if (!prevProps) return false

const cacheKey = callForString(chunkName, props)
Expand All @@ -149,7 +161,8 @@ export default function requireUniversalModule<Props: Props>(
requireSync,
requireAsync,
addModule,
shouldUpdate
shouldUpdate,
asyncOnly
}
}

Expand Down
Binary file added tests-screenshot-1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added tests-screenshot-2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed tests-screenshot.png
Binary file not shown.

0 comments on commit 0311e42

Please sign in to comment.