-
Notifications
You must be signed in to change notification settings - Fork 13
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* feat(component): styles * fix(component): effect depends on comp * chore(mson): v2.10.0
- Loading branch information
Showing
3 changed files
with
59 additions
and
52 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,58 +1,65 @@ | ||
import React from 'react'; | ||
import React, { useState, useEffect } from 'react'; | ||
import InnerComponent from './inner-component'; | ||
import compiler from 'mson/lib/compiler'; | ||
import attach from './attach'; | ||
import useComponent from './use-component'; | ||
import { makeStyles } from '@material-ui/core/styles'; | ||
|
||
export class Component extends React.PureComponent { | ||
state = { component: null }; | ||
const getOrZero = (value) => (value ? value : 0); | ||
|
||
createComponent() { | ||
const { definition } = this.props; | ||
this.setState({ component: compiler.newComponent(definition) }); | ||
} | ||
const useStyles = makeStyles((theme) => ({ | ||
root: (props) => { | ||
const { marginTop, marginRight, marginBottom, marginLeft } = props; | ||
return { | ||
marginTop: theme.spacing(getOrZero(marginTop)), | ||
marginRight: theme.spacing(getOrZero(marginRight)), | ||
marginBottom: theme.spacing(getOrZero(marginBottom)), | ||
marginLeft: theme.spacing(getOrZero(marginLeft)), | ||
}; | ||
}, | ||
})); | ||
|
||
componentDidMount() { | ||
if (this.props.definition) { | ||
this.createComponent(); | ||
} | ||
} | ||
export default function Component(props) { | ||
const { component, definition, ...childProps } = props; | ||
const [compiledComponent, setCompiledComponent] = useState(null); | ||
|
||
componentWillUnmount() { | ||
const { component } = this.state; | ||
const { hidden, styles } = useComponent(component, ['hidden', 'styles']); | ||
const styleProps = styles ? styles.get() : {}; | ||
const classes = useStyles(styleProps); | ||
|
||
// Did we use a definition to define a component in the state? | ||
if (component) { | ||
// Fire the unmount before we destroy the component so that the event is not lost | ||
component.emitChange('unmount'); | ||
// Should we use the component generated from the definition? | ||
const comp = component ? component : compiledComponent; | ||
|
||
// Remove all listeners to prevent listener leaks | ||
this.state.component.destroy(); | ||
// Compile the component when the definition changes | ||
useEffect(() => { | ||
if (definition) { | ||
setCompiledComponent(compiler.newComponent(definition)); | ||
} | ||
} | ||
}, [definition]); | ||
|
||
componentDidUpdate(prevProps) { | ||
// Is the definition changing? | ||
if (this.props.definition !== prevProps.definition) { | ||
this.createComponent(); | ||
} | ||
} | ||
|
||
render() { | ||
const { definition, component, ...childProps } = this.props; | ||
let comp = component; | ||
useEffect(() => { | ||
return () => { | ||
// Unmount. Did we use a definition to define a component in the state? | ||
if (comp) { | ||
// Fire the unmount before we destroy the component so that the event is not lost | ||
comp.emitChange('unmount'); | ||
|
||
// Should we use the component generated from the definition? | ||
if (!component) { | ||
comp = this.state.component; | ||
} | ||
// Remove all listeners to prevent listener leaks | ||
comp.destroy(); | ||
} | ||
}; | ||
}, [comp]); | ||
|
||
// Note: the component can be falsy, e.g. it has not yet been defined | ||
if (comp && comp.get('hidden')) { | ||
return null; | ||
// Note: the component can be falsy, e.g. it has not yet been defined | ||
if (comp && hidden) { | ||
return null; | ||
} else { | ||
// As a slight optimization, only display a wrapping tag if styles is truthy | ||
const innerComponent = <InnerComponent component={comp} {...childProps} />; | ||
if (styles) { | ||
// Use a div so that we have a block-level element that supports vertical margins | ||
return <div className={classes.root}>{innerComponent}</div>; | ||
} else { | ||
return <InnerComponent component={comp} {...childProps} />; | ||
return innerComponent; | ||
} | ||
} | ||
} | ||
|
||
export default attach(['hidden'])(Component); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters