refactor: Use ES6 classes instead of createClass

This commit is contained in:
Tom MacWright
2017-05-11 11:04:12 -04:00
committed by Tom MacWright
parent 5657bb232a
commit f5c5f86b24
9 changed files with 89 additions and 106 deletions

View File

@ -1,8 +1,8 @@
import React from 'react';
import Navigation from './navigation';
import PropTypes from 'prop-types';
import Content from './content';
import RoundedToggle from './rounded_toggle';
import PureRenderMixin from 'react-pure-render/mixin';
import GithubSlugger from 'github-slugger';
import debounce from 'lodash.debounce';
import { brandNames, brandClasses } from '../custom';
@ -41,13 +41,13 @@ let debouncedReplaceState = debounce(hash => {
window.history.replaceState('', '', hash);
}, 100);
var App = React.createClass({
mixins: [PureRenderMixin],
propTypes: {
content: React.PropTypes.string.isRequired,
ast: React.PropTypes.object.isRequired
},
getInitialState() {
export default class App extends React.PureComponent {
static propTypes = {
content: PropTypes.string.isRequired,
ast: PropTypes.object.isRequired
}
constructor(props) {
super(props);
var active = 'Introduction';
if (process.browser) {
@ -70,7 +70,7 @@ var App = React.createClass({
active = headingForHash.children[0].value;
}
}
return {
this.state = {
// media queryMatches
mqls: mqls,
// object of currently matched queries, like { desktop: true }
@ -82,7 +82,7 @@ var App = React.createClass({
showNav: false
};
} else {
return {
this.state = {
mqls: { },
queryMatches: {
desktop: true
@ -92,17 +92,17 @@ var App = React.createClass({
showNav: false
};
}
},
}
toggleNav() {
this.setState({ showNav: !this.state.showNav });
},
}
componentDidMount() {
this.mediaQueryChanged();
this.onScroll = debounce(this.onScrollImmediate, 100);
document.addEventListener('scroll', this.onScroll);
this.onScrollImmediate();
},
onScrollImmediate() {
}
onScrollImmediate = () => {
var sections = document.querySelectorAll('div.section');
if (!sections.length) return;
for (var i = 0; i < sections.length; i++) {
@ -114,7 +114,7 @@ var App = React.createClass({
return;
}
}
},
}
mediaQueryChanged() {
this.setState({
queryMatches: this.state.mqls.reduce((memo, q) => {
@ -122,19 +122,19 @@ var App = React.createClass({
return memo;
}, {})
});
},
}
componentWillUnmount() {
this.state.mqls.forEach(q => q.removeListener(this.mediaQueryChanged));
document.body.removeEventListener('scroll', this.onScroll);
},
onChangeLanguage(language) {
}
onChangeLanguage = (language) => {
this.setState({ language }, () => {
if (window.history) {
window.history.pushState(null, null,
`?${qs.stringify({ language: language.title })}${window.location.hash}`);
}
});
},
}
componentDidUpdate(_, prevState) {
if (prevState.activeSection !== this.state.activeSection) {
// when the section changes, replace the hash
@ -144,7 +144,7 @@ var App = React.createClass({
// when the language changes, use the hash to set scroll
window.location.hash = window.location.hash;
}
},
}
navigationItemClicked(activeSection) {
setTimeout(() => {
this.setState({ activeSection });
@ -152,12 +152,12 @@ var App = React.createClass({
if (!this.state.queryMatches.desktop) {
this.toggleNav();
}
},
}
toggleColumnMode() {
this.setState({
columnMode: this.state.columnMode === 1 ? 2 : 1
});
},
}
render() {
let ast = JSON.parse(JSON.stringify(this.props.ast));
let { activeSection, queryMatches, showNav, columnMode } = this.state;
@ -237,6 +237,4 @@ var App = React.createClass({
</div>);
}
});
module.exports = App;
}

View File

@ -1,14 +1,14 @@
import React from 'react';
import PropTypes from 'prop-types';
import Section from './section';
import PureRenderMixin from 'react-pure-render/mixin';
import GithubSlugger from 'github-slugger';
import { transformURL } from '../custom';
let slugger = new GithubSlugger();
let slug = title => { slugger.reset(); return slugger.slug(title); };
var roundedToggleOptionType = React.PropTypes.shape({
title: React.PropTypes.string,
value: React.PropTypes.string
var roundedToggleOptionType = PropTypes.shape({
title: PropTypes.string,
value: PropTypes.string
});
function chunkifyAST(ast, language) {
@ -71,24 +71,21 @@ function chunkifyAST(ast, language) {
});
}
var Content = React.createClass({
mixins: [PureRenderMixin],
propTypes: {
ast: React.PropTypes.object.isRequired,
export default class Content extends React.PureComponent {
static propTypes = {
ast: PropTypes.object.isRequired,
language: roundedToggleOptionType,
leftClassname: React.PropTypes.string.isRequired,
rightClassname: React.PropTypes.string.isRequired
},
leftClassname: PropTypes.string.isRequired,
rightClassname: PropTypes.string.isRequired
}
render() {
let { ast, language, leftClassname, rightClassname } = this.props;
return (<div className='clearfix'>
{chunkifyAST(ast, language.value).map((chunk, i) => <Section
{chunkifyAST(ast, language.value).map((chunk, i) => (<Section
leftClassname={leftClassname}
rightClassname={rightClassname}
chunk={chunk}
key={i} />)}
key={i} />))}
</div>);
}
});
module.exports = Content;
}

View File

@ -1,5 +1,5 @@
import React from 'react';
import PureRenderMixin from 'react-pure-render/mixin';
import PropTypes from 'prop-types';
import NavigationItem from './navigation_item';
import { footerContent } from '../custom';
@ -23,13 +23,12 @@ function getAllInSection(headings, idx) {
return activeHeadings;
}
var Navigation = React.createClass({
mixins: [PureRenderMixin],
propTypes: {
ast: React.PropTypes.object.isRequired,
activeSection: React.PropTypes.string,
navigationItemClicked: React.PropTypes.func.isRequired
},
export default class Navigation extends React.PureComponent {
static propTypes = {
ast: PropTypes.object.isRequired,
activeSection: PropTypes.string,
navigationItemClicked: PropTypes.func.isRequired
}
render() {
var activeHeadings = [];
let headings = this.props.ast.children
@ -91,6 +90,4 @@ var Navigation = React.createClass({
{footerContent}
</div>);
}
});
module.exports = Navigation;
}

View File

@ -1,17 +1,16 @@
import React from 'react';
import PureRenderMixin from 'react-pure-render/mixin';
import PropTypes from 'prop-types';
var NavigationItem = React.createClass({
mixins: [PureRenderMixin],
propTypes: {
sectionName: React.PropTypes.string.isRequired,
active: React.PropTypes.bool.isRequired,
onClick: React.PropTypes.func.isRequired,
href: React.PropTypes.string.isRequired
},
onClick() {
export default class NavigationItem extends React.PureComponent {
static propTypes = {
sectionName: PropTypes.string.isRequired,
active: PropTypes.bool.isRequired,
onClick: PropTypes.func.isRequired,
href: PropTypes.string.isRequired
}
onClick = () => {
this.props.onClick(this.props.sectionName);
},
}
render() {
var {sectionName, href, active} = this.props;
return (<a
@ -21,6 +20,4 @@ var NavigationItem = React.createClass({
{sectionName}
</a>);
}
});
module.exports = NavigationItem;
}

View File

@ -1,50 +1,46 @@
import React from 'react';
import PureRenderMixin from 'react-pure-render/mixin';
import PropTypes from 'prop-types';
var roundedToggleOptionType = React.PropTypes.shape({
title: React.PropTypes.string,
value: React.PropTypes.string
var roundedToggleOptionType = PropTypes.shape({
title: PropTypes.string,
value: PropTypes.string
});
var RoundedToggle = React.createClass({
mixins: [PureRenderMixin],
propTypes: {
options: React.PropTypes.arrayOf(roundedToggleOptionType).isRequired,
export default class RoundedToggle extends React.PureComponent {
static propTypes = {
options: PropTypes.arrayOf(roundedToggleOptionType).isRequired,
active: roundedToggleOptionType,
short: React.PropTypes.bool,
onChange: React.PropTypes.func.isRequired
},
short: PropTypes.bool,
onChange: PropTypes.func.isRequired
}
render() {
let { options, active } = this.props;
return (<div className='rounded-toggle inline short'>
{options.map(option =>
<RoundedToggleOption
(<RoundedToggleOption
key={option.value}
option={option}
short={this.props.short}
onClick={this.props.onChange}
className={`strong ${option.value === active.value ? 'active': ''}`} />)}
className={`strong ${option.value === active.value ? 'active': ''}`} />))}
</div>);
}
});
}
var RoundedToggleOption = React.createClass({
mixins: [PureRenderMixin],
propTypes: {
class RoundedToggleOption extends React.PureComponent {
static propTypes = {
option: roundedToggleOptionType,
className: React.PropTypes.string.isRequired,
short: React.PropTypes.bool,
onClick: React.PropTypes.func.isRequired
},
onClick() {
className: PropTypes.string.isRequired,
short: PropTypes.bool,
onClick: PropTypes.func.isRequired
}
onClick = () => {
this.props.onClick(this.props.option);
},
}
render() {
let { className, option } = this.props;
return (<a
onClick={this.onClick}
className={className}>{this.props.short ? option.short : option.title}</a>);
}
});
module.exports = RoundedToggle;
}

View File

@ -1,8 +1,8 @@
import React from 'react';
import remark from 'remark';
import PropTypes from 'prop-types';
import remarkHTML from 'remark-html';
import remarkHighlight from '../highlight';
import PureRenderMixin from 'react-pure-render/mixin';
import { postHighlight, remarkPlugins } from '../custom';
function renderHighlighted(nodes) {
@ -19,13 +19,12 @@ function renderHighlighted(nodes) {
};
}
var Section = React.createClass({
mixins: [PureRenderMixin],
propTypes: {
chunk: React.PropTypes.object.isRequired,
leftClassname: React.PropTypes.string.isRequired,
rightClassname: React.PropTypes.string.isRequired
},
export default class Section extends React.PureComponent {
static propTypes = {
chunk: PropTypes.object.isRequired,
leftClassname: PropTypes.string.isRequired,
rightClassname: PropTypes.string.isRequired
}
render() {
let { chunk, leftClassname, rightClassname } = this.props;
let { left, right, preview } = chunk;
@ -40,6 +39,4 @@ var Section = React.createClass({
dangerouslySetInnerHTML={renderHighlighted(right)} />}
</div>);
}
});
module.exports = Section;
}