Repository URL to install this package:
Version:
0.9.6 ▾
|
import { observable, action } from 'xmobx/mobx'
// # example
// 1. observable
class EhState {
// isNotObserved = true
@observable isVisible: boolean = false
}
// 2. action
// const list =
class EhStateWithAction {
@observable isVisible: boolean = false
@action
toggle() {
this.isVisible = !this.isVisible
}
}
// === lifecycle ===
class Uncommon extends React.Component {
// error boundary is just this
componentDidCatch() {
// error
}
componentWillReceiveProps() {
//
}
shouldComponentUpdate() {
// do not need
return false
}
componentWillUpdate() {
//
}
render() {
return 'will, render, did'
}
componentDidUpdate() {
//
}
}
// how mobx works sudo code
const tracking = {
[state.isVisible]: []
}
let currentlyListening = undefined
const listeners = []
const secretState = {
get isVisible() {
if (currentlyListening) {
listeners.push(currentlyListening)
}
//
return state.isVisible
},
set isVisible(value) {
// first it checks if it is the same value, so it doesn't nofiy extra
const change = {
key: 'isVisible',
value: value,
oldValue: this.$mobxSecret.value,
}
this.$mobxSecret.value = value
if (listeners.length) {
listeners.forEach(listener => listener(change))
}
}
}
@observer
class SmartObserving extends React.Component {
_render() {
console.log(state.isVisible)
return 'eh'
}
render() {
currentlyListening = this
const rendered = this._render()
currentlyListening = undefined
return rendered
}
}
// ===
const state = new EhStateWithAction()
// 3. observer
// ===
// - component
import React from 'react'
import { observer } from 'xmobx/mobx-react'
@observer
class Eh extends React.Component {}
// ===
// - observing as a fn
import { observe } from 'xmobx/mobx'
observe(state, () => {
console.log('every time state changes')
})
observe(state, 'isVisible', () => {
console.log('every time state.isVisible changes')
})
// only 1
const singleState = state
const countState = observable({
updateCount: 0,
increment() {
// void
},
})
countState.increment = action(() => {
countState.updateCount += 1
})
// @observer
class EhObserverExample extends React.Component {
componentDidMount() {
const onInterval = () => {
// turn on and off every second
// like a kid who discovered a light switch for the first time
state.toggle()
}
setInterval(onInterval, 1000)
observe(state, () => {
countState.increment()
this.forceUpdate()
})
}
render() {
return <span>updated: {countState.updateCount}</span>
}
}
class Lifecycle extends React.Component {
componentDidMount() {
// happens 1x after render in the browser
// updates to things should happen here
// after this, it will update 1x
}
componentWillUnmount() {
// clean up when it's no longer used
// example, when you go from 1 page to another, things unmount
// always stop listening to things like click events here
}
render() {
return 'known'
}
componentWillMount() {
// this is used for server side rendering and rehydration
// since it happens 1x on server & 1x in browser
}
}
// ========= multi ===
function createMultiState() {
const newState = new EhStateWithAction()
return newState
}
// now we can have 10, and they all have their own
// class MultiStateObserver extends React.Component {
// // state = createMultiState()
// constructor(...args) {
// super(...args)
// this.thingToObserve = new EhStateWithAction()
// }
// }
class MultiStateObserver extends React.Component {
static defaultProps = {
// @note - you can't have a getter on React.Prop
// so it will be called by react
get state() {
return new EhStateWithAction()
},
}
}
// would never call the getter
// const eh = ''
// <MultiStateObserver state={eh} />
// would call the getter
// =>
// props = Object.freeze({
// state: new EhStateWithAction()
// })
// === how defaultProps works ===
// @todo console.table console.group
function isUniq(value, index, arr) {
console.assert(Array.isArray(arr), '3rd arg is the instance')
const firstIndex = arr.indexOf(value)
const isFirst = firstIndex === index
// console.table([
// ['value', value],
// ['isFirst', isFirst],
// ['firstIndex', firstIndex],
// ])
// console.log('\n\n\n')
return isFirst
}
// ['a', 2, 'a', 'b'].filter(isUniq)
// const list = ['a', 2, 'a']
// list.filter(isUniq)
function keys(obj) {
const names = Object.getOwnPropertyNames(obj)
const descriptors = Object.getOwnPropertyDescriptors(obj)
const renamedDescriptors = Object.keys(descriptors)
const symbols = Object.getOwnPropertySymbols(obj)
const objKeys = Object.keys(obj)
const list = []
// eslint-disable-next-line
// tslint:disable forin
for (const index in obj) {
list.push(index)
}
return list
.concat(objKeys)
.concat(names)
.concat(renamedDescriptors)
.concat(symbols)
.filter(isUniq)
}
function mergePropsAndDefaultProps(props, defaultProps) {
// make a copy of props
const frozenProps = Object.assign({}, props)
keys(defaultProps).forEach(key => {
// 1. if props that are passed in do not have this key
// 2. calling hasOwnProperty WILL NOT TRIGGER A GETTER
if (!Object.prototype.hasOwnProperty.call(props, key)) {
console.debug('does have property: ', key)
// THIS WILL TRIGGER ANY GETTERS
frozenProps[key] = defaultProps[key]
} else {
console.debug('does not have property: ', key)
}
})
Object.freeze(frozenProps)
return frozenProps
}
function example() {
const props = {
eh: true,
}
const defaultProps = {
eh: false,
moose: true,
[Symbol.toPrimitive](type) {
console.debug('(default)Props.toPrimitive')
if (type === 'number') {
return -42
} else {
// also has options of type = 'string' | 'number' | 'default' | undefined
return 'eh'
}
},
get canada() {
console.info('accessing defaultProps.canada')
return 'eh'
},
}
const proto = {
protoProp: 0x1,
}
Object.setPrototypeOf(defaultProps, proto)
Object.defineProperty(defaultProps, 'hidden', {
configurable: true,
enumerable: false,
value: 10,
})
return mergePropsAndDefaultProps(props, defaultProps)
}
example()
// <MultiStateObserver />
// class MultiStateObserver extends React.Component {
// constructor(props) {
// super(props)
// console.assert(
// Object.isExtensible(props) === false,
// 'props is frozen, cannot change'
// )
// if (props.state === undefined) {
// this.state = new EhStateWithAction()
// } else {
// this.state = props.state
// }
// }
// }