Break down Header and Footer into simpler components (#7)

This commit is contained in:
Scott Mikula 2017-03-16 13:16:18 -07:00 коммит произвёл GitHub
Родитель 03e473797d
Коммит e4b93d2543
10 изменённых файлов: 120 добавлений и 83 удалений

Просмотреть файл

@ -1,8 +1,8 @@
import * as React from 'react';
import Header from './Header';
import Header from './header/Header';
import Main from './Main';
import Footer from './Footer';
import Footer from './footer/Footer';
export default function App() {
return (

Просмотреть файл

@ -1,33 +0,0 @@
import * as React from 'react';
import {observer} from 'mobx-react';
import Store from '../store/store';
import removeAllCompleted from '../actions/removeAllCompleted';
import setFilter from '../actions/setFilter';
import {FilterType} from '../store/schema';
@observer
export default class Footer extends React.Component<any, any> {
onClearCompleted = () => {
removeAllCompleted();
}
onSetFilter = (filter: FilterType) => {
setFilter(filter);
}
render() {
let {itemsLeft, filter} = Store;
return (
<footer className="footer">
<span className="todo-count">{itemsLeft} Left</span>
<ul className="filters">
<li><a href="#" onClick={() => this.onSetFilter(FilterType.All)} className={filter == FilterType.All ? "selected" : ""}>All</a></li>
<li><a href="#" onClick={() => this.onSetFilter(FilterType.Active)} className={filter == FilterType.Active ? "selected" : ""}>Active</a></li>
<li><a href="#" onClick={() => this.onSetFilter(FilterType.Completed)} className={filter == FilterType.Completed ? "selected" : ""}>Completed</a></li>
</ul>
<button className="clear-completed" onClick={this.onClearCompleted}>Clear completed</button>
</footer>
);
}
}

Просмотреть файл

@ -1,46 +0,0 @@
import * as React from 'react';
import { observer } from 'mobx-react';
import { reactive } from 'satcheljs-react';
import store from '../store/store';
import addItem from '../actions/addItem';
import updateTextboxValue from '../actions/updateTextboxValue';
interface HeaderProps {
textboxValue?: string;
}
@reactive({
textboxValue: () => store.textboxValue,
})
export default class Header extends React.Component<HeaderProps, {}> {
private textbox: HTMLInputElement;
onKeyPress = (e) => {
if (e.key == "Enter") {
addItem(this.textbox.value);
}
return true;
}
onChange = () => {
// Update the store every time the textbox value changes
updateTextboxValue(this.textbox.value);
}
render() {
return (
<header className="header">
<h1>todos</h1>
<input
ref={ref => this.textbox = ref}
className="new-todo"
placeholder="What needs to be done?"
value={this.props.textboxValue}
autoFocus={true}
onChange={this.onChange}
onKeyPress={this.onKeyPress} />
</header>
)
}
}

Просмотреть файл

@ -31,7 +31,6 @@ export default class Main extends React.Component<any, any> {
}
onToggleEdit = (id: string) => {
let inputElement = this.refs["edit_" + id] as HTMLInputElement;
toggleEditItem(id);
}

Просмотреть файл

@ -0,0 +1,28 @@
import * as React from 'react';
import { reactive } from 'satcheljs-react';
import { FilterType } from '../../store/schema';
import store from '../../store/store';
import setFilter from '../../actions/setFilter';
interface FilterButtonProps {
filter: FilterType;
text: string;
currentFilter?: FilterType;
}
export default reactive({
currentFilter: () => store.filter
})(
function FilterButton(props: FilterButtonProps) {
return (
<li>
<a
href="#"
onClick={() => setFilter(props.filter)}
className={props.currentFilter == props.filter ? "selected" : ""}
>
{props.text}
</a>
</li>
);
});

Просмотреть файл

@ -0,0 +1,19 @@
import * as React from 'react';
import removeAllCompleted from '../../actions/removeAllCompleted';
import { FilterType } from '../../store/schema';
import ItemsLeftCount from './ItemsLeftCount';
import FilterButton from './FilterButton';
export default function Footer() {
return (
<footer className="footer">
<ItemsLeftCount />
<ul className="filters">
<FilterButton filter={FilterType.All} text="All" />
<FilterButton filter={FilterType.Active} text="Active" />
<FilterButton filter={FilterType.Completed} text="Completed" />
</ul>
<button className="clear-completed" onClick={removeAllCompleted}>Clear completed</button>
</footer>
);
}

Просмотреть файл

@ -0,0 +1,16 @@
import * as React from 'react';
import { reactive } from 'satcheljs-react';
import store from '../../store/store';
interface ItemsLeftCountProps {
itemsLeft?: number;
}
export default reactive({
itemsLeft: () => store.itemsLeft
})(
function ItemsLeftCount(props: ItemsLeftCountProps) {
return (
<span className="todo-count">{props.itemsLeft} Left</span>
);
});

Просмотреть файл

@ -0,0 +1,11 @@
import * as React from 'react';
import NewTaskInput from './NewTaskInput';
export default function Header() {
return (
<header className="header">
<h1>todos</h1>
<NewTaskInput />
</header>
);
}

Просмотреть файл

@ -0,0 +1,42 @@
import * as React from 'react';
import { reactive } from 'satcheljs-react';
import store from '../../store/store';
import addItem from '../../actions/addItem';
import updateTextboxValue from '../../actions/updateTextboxValue';
interface NewTaskInputProps {
textboxValue?: string;
}
@reactive({
textboxValue: () => store.textboxValue,
})
export default class NewTaskInput extends React.Component<NewTaskInputProps, {}> {
private textbox: HTMLInputElement;
onKeyPress = (e) => {
if (e.key == "Enter") {
addItem(this.textbox.value);
}
return true;
}
onChange = () => {
// Update the store every time the textbox value changes
updateTextboxValue(this.textbox.value);
}
render() {
return (
<input
ref={ref => this.textbox = ref}
className="new-todo"
placeholder="What needs to be done?"
value={this.props.textboxValue}
autoFocus={true}
onChange={this.onChange}
onKeyPress={this.onKeyPress} />
)
}
}

Просмотреть файл

@ -6,7 +6,8 @@
"moduleResolution": "node",
"sourceMap": true,
"experimentalDecorators": true,
"outDir": "dist"
"outDir": "dist",
"noUnusedLocals": true
},
"compileOnSave": false,
"exclude": [