Skip to content

Commit

Permalink
rearchitesting of preact connector. fix context problems
Browse files Browse the repository at this point in the history
  • Loading branch information
arshaw committed Apr 29, 2020
1 parent fb95b5f commit f58b159
Show file tree
Hide file tree
Showing 10 changed files with 127 additions and 82 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@
"mkdirp": "^0.5.1",
"moment": "^2.24.0",
"moment-timezone": "^0.5.26",
"preact": "^10.0.5",
"preact": "^10.4.1",
"react": "^16.13.1",
"react-dom": "^16.13.1",
"rollup": "^1.28.0",
Expand Down
13 changes: 4 additions & 9 deletions packages/common/src/vdom-util.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Component, Ref } from './vdom'
import { ViewContext, ViewContextType } from './ViewContext'
import { ViewContextType } from './ViewContext'
import { __assign } from 'tslib'
import { compareObjs, EqualityFuncs, getUnequalProps } from './util/object'

Expand All @@ -11,24 +11,19 @@ export abstract class BaseComponent<Props={}, State={}> extends Component<Props,
static addStateEquality = addStateEquality
static contextType = ViewContextType

context: ViewContext
propEquality: EqualityFuncs<Props>
stateEquality: EqualityFuncs<State>
debug: boolean

shouldComponentUpdate(nextProps: Props, nextState: State, nextContext: ViewContext) {

shouldComponentUpdate(nextProps: Props, nextState: State) {

if (this.debug) {
console.log(getUnequalProps(nextProps, this.props), getUnequalProps(nextState, this.state))

if (this.context !== nextContext) {
console.log('context is different')
}
}

return !compareObjs(this.props, nextProps, this.propEquality) ||
!compareObjs(this.state, nextState, this.stateEquality) ||
this.context !== nextContext
!compareObjs(this.state, nextState, this.stateEquality)
}

}
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/Calendar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {
OptionsInput, Action, CalendarContent, render, h, DelayedRunner, guid, CssDimValue, applyStyleProp,
CalendarApi, computeCalendarClassNames, computeCalendarHeight, isArraysEqual, CalendarDataProvider, CalendarData
} from '@fullcalendar/common'
import { flushToDom } from './utils'
import { flushToDom } from './vdom'


export class Calendar extends CalendarApi {
Expand Down
6 changes: 1 addition & 5 deletions packages/core/src/main.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@

import './vdom'
// import '../../../packages-contrib/react/src/vdom'

export { flushToDom } from './vdom' // for tests. does SIDE EFFECTS
export { Calendar } from './Calendar'
export { flushToDom } from './utils' // tests need this

export * from '@fullcalendar/common'
66 changes: 66 additions & 0 deletions packages/core/src/preact-hacks.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { options, render, h, Component, createContext as origCreateContext } from 'preact'


// TODO: lock version
// TODO: link gh issues


export function flushToDom() {
let oldDebounceRendering = options.debounceRendering // orig
let callbackQ = []

function execCallbackSync(callback) {
callbackQ.push(callback)
}

options.debounceRendering = execCallbackSync
render(h(FakeComponent, {}), document.createElement('div'))

while (callbackQ.length) {
callbackQ.shift()()
}

options.debounceRendering = oldDebounceRendering
}

class FakeComponent extends Component {
render() { return h('div', {}) }
componentDidMount() { this.setState({}) }
}


export function createContext<T>(defaultValue: T) {
let ContextType = origCreateContext<T>(defaultValue)
let origProvider = ContextType.Provider

ContextType.Provider = function() {
let isNew = !this.getChildContext
let children = origProvider.apply(this, arguments as any)

if (isNew) {
let subs = []

this.shouldComponentUpdate = (_props) => {
if (this.props.value !== _props.value) {
subs.some(c => {
c.context = _props.value
c.forceUpdate()
})
}
}

this.sub = (c) => {
subs.push(c)
let old = c.componentWillUnmount
c.componentWillUnmount = () => {
subs.splice(subs.indexOf(c), 1)
old && old.call(c)
}
}
}

return children
}

return ContextType
}
27 changes: 0 additions & 27 deletions packages/core/src/utils.ts

This file was deleted.

31 changes: 31 additions & 0 deletions packages/core/src/vdom-preact.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import * as preact from 'preact'
import * as hacks from './preact-hacks'
export { flushToDom } from './preact-hacks'

declare global {
namespace FullCalendarVDom {
export import Ref = preact.Ref
export import RefObject = preact.RefObject
export import ComponentType = preact.ComponentType
export type VNode = preact.VNode // will NOT forward the props type
export import Context = preact.Context
export import Component = preact.Component
export import ComponentChild = preact.ComponentChild
export import ComponentChildren = preact.ComponentChildren
export import h = preact.h
export import render = preact.render
export import createRef = preact.createRef
export import Fragment = preact.Fragment
export import createContext = hacks.createContext
export type VUIEvent = UIEvent
}
}

window.FullCalendarVDom = {
Component: preact.Component,
h: preact.h,
render: preact.render,
createRef: preact.createRef,
Fragment: preact.Fragment,
createContext: hacks.createContext
}
5 changes: 5 additions & 0 deletions packages/core/src/vdom-react.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@

import '../../../packages-contrib/react/src/vdom'

export function flushToDom() {
}
30 changes: 2 additions & 28 deletions packages/core/src/vdom.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1,3 @@
import * as preact from 'preact'

declare global {
namespace FullCalendarVDom {
export import Ref = preact.Ref
export import RefObject = preact.RefObject
export import ComponentType = preact.ComponentType
export type VNode = preact.VNode // will NOT forward the props type
export import Context = preact.Context
export import Component = preact.Component
export import ComponentChild = preact.ComponentChild
export import ComponentChildren = preact.ComponentChildren
export import h = preact.h
export import render = preact.render
export import createRef = preact.createRef
export import Fragment = preact.Fragment
export import createContext = preact.createContext
export type VUIEvent = UIEvent
}
}

window.FullCalendarVDom = {
Component: preact.Component,
h: preact.h,
render: preact.render,
createRef: preact.createRef,
Fragment: preact.Fragment,
createContext: preact.createContext
}
export * from './vdom-preact'
// export * from './vdom-react'
27 changes: 16 additions & 11 deletions scripts/lib/rollup-modules.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,26 @@ const { pkgStructs } = require('./pkg-struct')
const { copyFile } = require('./util')


// TODO: wait for tsc to finish!!!
// needed to have this in separate file because rollup wasn't understanding that it has side effects and needed to go before the @fullcalendar/core import
// added bonuses:
// - the import statement doesn't import any vars, which will maybe hint to the build env that there are side effects
// - rollup-plugin-dts needed to handle the .d.ts files separately anyway
copyFile( // promise :(
'tmp/tsc-output/packages/core/src/vdom.js',
'packages/core/dist/vdom.js'
)


module.exports = function(isDev) {
let configs = pkgStructs.filter((pkgStruct) => !pkgStruct.isBundle)
.map((pkgStruct) => buildPkgConfig(pkgStruct, isDev))

// needed to have this in separate file because rollup wasn't understanding that it has side effects and needed to go before the @fullcalendar/core import
// added bonuses:
// - the import statement doesn't import any vars, which will maybe hint to the build env that there are side effects
// - rollup-plugin-dts needed to handle the .d.ts files separately anyway
configs.push({
input: 'tmp/tsc-output/packages/core/src/vdom.js',
output: {
file: 'packages/core/dist/vdom.js',
format: 'esm',
sourcemap: isDev
},
external(id) {
return isNamedPkg(id)
}
})

return configs
}

Expand Down

0 comments on commit f58b159

Please sign in to comment.