Merge pull request #410 from jorilallo/remove-set-state

Removes all uses of setState
This commit is contained in:
Jori Lallo 2017-11-12 17:22:32 -08:00 committed by GitHub
commit 00a7985383
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 70 additions and 86 deletions

View File

@ -1,5 +1,6 @@
// @flow
import React, { Component } from 'react';
import { observable } from 'mobx';
import { observer } from 'mobx-react';
import Popover from 'components/Popover';
import styled from 'styled-components';
@ -27,13 +28,10 @@ type Props = {
@observer
class DocumentViews extends Component {
@observable opened: boolean = false;
anchor: HTMLElement;
store: DocumentViewersStore;
props: Props;
state: {
opened: boolean,
};
state = {};
constructor(props: Props) {
super(props);
@ -41,11 +39,11 @@ class DocumentViews extends Component {
}
openPopover = () => {
this.setState({ opened: true });
this.opened = true;
};
closePopover = () => {
this.setState({ opened: false });
this.opened = false;
};
setRef = (ref: HTMLElement) => {
@ -58,7 +56,7 @@ class DocumentViews extends Component {
<a ref={this.setRef} onClick={this.openPopover}>
Viewed {this.props.count} {this.props.count === 1 ? 'time' : 'times'}
</a>
{this.state.opened && (
{this.opened && (
<Popover anchor={this.anchor} onClose={this.closePopover}>
<DocumentViewers
onMount={this.store.fetchViewers}

View File

@ -1,6 +1,7 @@
// @flow
import React, { Component } from 'react';
import { inject } from 'mobx-react';
import { observable } from 'mobx';
import { observer, inject } from 'mobx-react';
import { injectGlobal } from 'styled-components';
import { color } from 'shared/styles/constants';
import invariant from 'invariant';
@ -22,6 +23,7 @@ type Props = {
history: Object,
};
// eslint-disable-next-line
injectGlobal`
.activeDropZone {
background: ${color.slateDark};
@ -33,14 +35,10 @@ injectGlobal`
}
`;
@observer
class DropToImport extends Component {
state: {
isImporting: boolean,
};
@observable isImporting: boolean = false;
props: Props;
state = {
isImporting: false,
};
importFile = async ({ file, documentId, collectionId, redirect }) => {
const reader = new FileReader();
@ -67,7 +65,7 @@ class DropToImport extends Component {
};
onDropAccepted = async (files = []) => {
this.setState({ isImporting: true });
this.isImporting = true;
try {
let collectionId = this.props.collectionId;
@ -86,7 +84,7 @@ class DropToImport extends Component {
} catch (err) {
// TODO: show error alert.
} finally {
this.setState({ isImporting: false });
this.isImporting = false;
}
};
@ -115,7 +113,7 @@ class DropToImport extends Component {
ref={this.props.dropzoneRef}
{...props}
>
{this.state.isImporting && <LoadingIndicator />}
{this.isImporting && <LoadingIndicator />}
{this.props.children}
</Dropzone>
);

View File

@ -1,5 +1,7 @@
// @flow
import React, { Component } from 'react';
import { observable } from 'mobx';
import { observer } from 'mobx-react';
import { Portal } from 'react-portal';
import styled from 'styled-components';
import _ from 'lodash';
@ -7,28 +9,20 @@ import type { State } from '../../types';
import FormattingToolbar from './components/FormattingToolbar';
import LinkToolbar from './components/LinkToolbar';
@observer
export default class Toolbar extends Component {
@observable active: boolean = false;
@observable focused: boolean = false;
@observable link: ?React$Element<any>;
@observable top: string = '';
@observable left: string = '';
props: {
state: State,
onChange: Function,
onChange: (state: State) => void,
};
menu: HTMLElement;
state: {
active: boolean,
focused: boolean,
link: React$Element<any>,
top: string,
left: string,
};
state = {
active: false,
focused: false,
link: null,
top: '',
left: '',
};
componentDidMount = () => {
this.update();
@ -39,11 +33,11 @@ export default class Toolbar extends Component {
};
handleFocus = () => {
this.setState({ focused: true });
this.focused = true;
};
handleBlur = () => {
this.setState({ focused: false });
this.focused = false;
};
get linkInSelection(): any {
@ -66,8 +60,11 @@ export default class Toolbar extends Component {
const link = this.linkInSelection;
if (state.isBlurred || (state.isCollapsed && !link)) {
if (this.state.active && !this.state.focused) {
this.setState({ active: false, link: null, top: '', left: '' });
if (this.active && !this.focused) {
this.active = false;
this.link = undefined;
this.top = '';
this.left = '';
}
return;
}
@ -79,32 +76,25 @@ export default class Toolbar extends Component {
// don't display toolbar for code blocks
if (state.startBlock.type === 'code') return;
const data = {
...this.state,
active: true,
link,
focused: !!link,
};
this.active = true;
this.focused = !!link;
this.link = link;
if (!_.isEqual(data, this.state)) {
const padding = 16;
const selection = window.getSelection();
const range = selection.getRangeAt(0);
const rect = range.getBoundingClientRect();
const padding = 16;
const selection = window.getSelection();
const range = selection.getRangeAt(0);
const rect = range.getBoundingClientRect();
if (rect.top === 0 && rect.left === 0) {
this.setState(data);
return;
}
const left =
rect.left + window.scrollX - this.menu.offsetWidth / 2 + rect.width / 2;
data.top = `${Math.round(
rect.top + window.scrollY - this.menu.offsetHeight
)}px`;
data.left = `${Math.round(Math.max(padding, left))}px`;
this.setState(data);
if (rect.top === 0 && rect.left === 0) {
return;
}
const left =
rect.left + window.scrollX - this.menu.offsetWidth / 2 + rect.width / 2;
this.top = `${Math.round(
rect.top + window.scrollY - this.menu.offsetHeight
)}px`;
this.left = `${Math.round(Math.max(padding, left))}px`;
};
setRef = (ref: HTMLElement) => {
@ -112,20 +102,21 @@ export default class Toolbar extends Component {
};
render() {
const link = this.state.link;
const style = {
top: this.state.top,
left: this.state.left,
top: this.top,
left: this.left,
};
return (
<Portal>
<Menu active={this.state.active} innerRef={this.setRef} style={style}>
{link && (
<LinkToolbar {...this.props} link={link} onBlur={this.handleBlur} />
)}
{!link && (
<Menu active={this.active} innerRef={this.setRef} style={style}>
{this.link ? (
<LinkToolbar
{...this.props}
link={this.link}
onBlur={this.handleBlur}
/>
) : (
<FormattingToolbar
onCreateLink={this.handleFocus}
{...this.props}

View File

@ -15,6 +15,7 @@ type Props = {
onRequestClose: () => void,
};
// eslint-disable-next-line
injectGlobal`
.ReactModal__Overlay {
z-index: 100;

View File

@ -1,5 +1,6 @@
// @flow
import React from 'react';
import React, { Component } from 'react';
import { observable } from 'mobx';
import { observer } from 'mobx-react';
import { Link } from 'react-router-dom';
import styled from 'styled-components';
@ -15,7 +16,7 @@ import { Label } from 'components/Labeled';
import SlackAuthLink from 'components/SlackAuthLink';
@observer
class Settings extends React.Component {
class Settings extends Component {
store: SettingsStore;
constructor() {
@ -89,7 +90,8 @@ class Settings extends React.Component {
}
}
class InlineForm extends React.Component {
@observer
class InlineForm extends Component {
props: {
placeholder: string,
buttonLabel: string,
@ -99,11 +101,9 @@ class InlineForm extends React.Component {
onSubmit: Function,
disabled?: ?boolean,
};
validationTimeout: number;
state = {
validationError: false,
};
@observable validationError: boolean = false;
validationTimeout: number;
componentWillUnmount() {
clearTimeout(this.validationTimeout);
@ -114,14 +114,9 @@ class InlineForm extends React.Component {
if (this.props.value) {
this.props.onSubmit();
} else {
this.setState({
validationError: true,
});
this.validationError = true;
this.validationTimeout = setTimeout(
() =>
this.setState({
validationError: false,
}),
() => (this.validationError = false),
2500
);
}
@ -129,17 +124,18 @@ class InlineForm extends React.Component {
render() {
const { placeholder, value, onChange, buttonLabel } = this.props;
const { validationError } = this.state;
return (
<form onSubmit={this.handleSubmit}>
<Flex auto>
<ApiKeyInput
type="text"
placeholder={validationError ? 'Please add a label' : placeholder}
placeholder={
this.validationError ? 'Please add a label' : placeholder
}
value={value || ''}
onChange={onChange}
validationError={validationError}
validationError={this.validationError}
/>
<Button type="submit" value={buttonLabel} />
</Flex>