Skip to content

Commit c150fdf

Browse files
committed
Refactor root container(s) to use react hook
1 parent 20698d6 commit c150fdf

File tree

19 files changed

+166
-292
lines changed

19 files changed

+166
-292
lines changed

README.md

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
A bare minimum react-mobx-webpack-typescript boilerplate with TodoMVC example.
44

5-
Note that this project does not include **Server-Side Rendering**, **Testing Frameworks** and other stuffs that makes the package unnecessarily complicated.
5+
Note that this project does not include **Server-Side Rendering**, **Testing Frameworks** and other stuffs that makes the package unnecessarily complicated.
66

77
Ideal for creating React apps from the scratch.
88

@@ -15,24 +15,18 @@ See also: [react-redux-typescript-boilerplate](https://github.com/rokoroku/react
1515
- [x] [React Router](https://github.com/ReactTraining/react-router) 4
1616
- [x] [Mobx](https://github.com/mobxjs/mobx) 5
1717
- [x] [Mobx React](https://github.com/mobxjs/mobx-react)
18-
- [x] [Mobx React Router](https://github.com/alisd23/mobx-react-router/)
19-
- [x] [Mobx React Devtools](https://github.com/mobxjs/mobx-react-devtools)
2018
- [x] [TodoMVC example](http://todomvc.com)
2119

2220
### Build tools
2321

2422
- [x] [Webpack](https://webpack.github.io) 4
25-
- [x] [Tree Shaking](https://webpack.js.org/guides/tree-shaking/)
26-
- [x] [Webpack Dev Server](https://github.com/webpack/webpack-dev-server)
23+
- [x] [React Hot Loader](https://github.com/gaearon/react-hot-loader)
2724
- [x] [Typescript Loader](https://github.com/TypeStrong/ts-loader)
2825
- [x] [PostCSS Loader](https://github.com/postcss/postcss-loader)
2926
- [x] [PostCSS Preset Env](https://preset-env.cssdb.org/)
3027
- [x] [CSS modules](https://github.com/css-modules/)
31-
- [x] [React Hot Loader](https://github.com/gaearon/react-hot-loader)
32-
- [x] [Mini CSS Extract Plugin](https://github.com/webpack-contrib/mini-css-extract-plugin)
3328
- [x] [HTML Webpack Plugin](https://github.com/ampedandwired/html-webpack-plugin)
3429

35-
3630
## Setup
3731

3832
```

src/app/components/Footer/index.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import * as style from './style.css';
44
import {
55
TodoFilter,
66
TODO_FILTER_TITLES,
7-
TODO_FILTER_TYPES
7+
TODO_FILTER_TYPES,
88
} from 'app/constants';
99

1010
export interface FooterProps {
@@ -35,7 +35,7 @@ export class Footer extends React.Component<FooterProps, FooterState> {
3535
const title = TODO_FILTER_TITLES[filter];
3636
const { filter: selectedFilter, onChangeFilter } = this.props;
3737
const className = classNames({
38-
[style.selected]: filter === selectedFilter
38+
[style.selected]: filter === selectedFilter,
3939
});
4040

4141
return (

src/app/components/TodoItem/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ export class TodoItem extends React.Component<TodoProps, TodoState> {
8484
const classes = classNames({
8585
[style.completed]: todo.completed,
8686
[style.editing]: this.state.editing,
87-
[style.normal]: !this.state.editing
87+
[style.normal]: !this.state.editing,
8888
});
8989

9090
return <li className={classes}>{element}</li>;

src/app/components/TodoItem/style.css

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,11 @@
1313
}
1414

1515
.normal .toggle:after {
16-
content: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="-10 -18 100 135"><circle cx="50" cy="50" r="50" fill="none" stroke="#ededed" stroke-width="3"/></svg>');
16+
content: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="-10 -18 100 135"><circle cx="50" cy="50" r="50" fill="none" stroke="%23ededed" stroke-width="3"/></svg>');
1717
}
1818

1919
.normal .toggle:checked:after {
20-
content: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="-10 -18 100 135"><circle cx="50" cy="50" r="50" fill="none" stroke="#bddad5" stroke-width="3"/><path fill="#5dc2af" d="M72 25L42 71 27 56l-4 4 20 20 34-52z"/></svg>');
20+
content: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="-10 -18 100 135"><circle cx="50" cy="50" r="50" fill="none" stroke="%23bddad5" stroke-width="3"/><path fill="%235dc2af" d="M72 25L42 71 27 56l-4 4 20 20 34-52z"/></svg>');
2121
}
2222

2323
.normal label {

src/app/components/TodoTextInput/index.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ export class TodoTextInput extends React.Component<
2121
constructor(props?: TodoTextInputProps, context?: any) {
2222
super(props, context);
2323
this.state = {
24-
text: this.props.text || ''
24+
text: this.props.text || '',
2525
};
2626
}
2727

@@ -50,7 +50,7 @@ export class TodoTextInput extends React.Component<
5050
const classes = classNames(
5151
{
5252
[style.edit]: this.props.editing,
53-
[style.new]: this.props.newTodo
53+
[style.new]: this.props.newTodo,
5454
},
5555
style.normal
5656
);

src/app/constants/index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1 @@
1-
export * from './stores';
21
export * from './todos';

src/app/constants/stores.ts

Lines changed: 0 additions & 2 deletions
This file was deleted.

src/app/constants/todos.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,23 @@
11
export enum TodoFilter {
22
ALL = 0,
33
ACTIVE,
4-
COMPLETED
4+
COMPLETED,
55
}
66

77
export const TODO_FILTER_TYPES = [
88
TodoFilter.ALL,
99
TodoFilter.ACTIVE,
10-
TodoFilter.COMPLETED
10+
TodoFilter.COMPLETED,
1111
];
1212

1313
export const TODO_FILTER_TITLES = {
1414
[TodoFilter.ALL]: 'All',
1515
[TodoFilter.ACTIVE]: 'Active',
16-
[TodoFilter.COMPLETED]: 'Completed'
16+
[TodoFilter.COMPLETED]: 'Completed',
1717
};
1818

1919
export const TODO_FILTER_LOCATION_HASH = {
2020
[TodoFilter.ALL]: '#',
2121
[TodoFilter.ACTIVE]: '#active',
22-
[TodoFilter.COMPLETED]: '#completed'
22+
[TodoFilter.COMPLETED]: '#completed',
2323
};

src/app/containers/Root/index.tsx

Lines changed: 0 additions & 19 deletions
This file was deleted.

src/app/containers/TodoApp/index.tsx

Lines changed: 0 additions & 103 deletions
This file was deleted.
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import * as React from 'react';
2+
import * as style from './style.css';
3+
import { observer } from 'mobx-react';
4+
import { useLocation, useHistory } from 'react-router';
5+
import { Header } from 'app/components/Header';
6+
import { Footer } from 'app/components/Footer';
7+
import { TodoList } from 'app/components/TodoList';
8+
import { TodoModel } from 'app/models';
9+
import { useTodoStore } from 'app/stores/TodoStore';
10+
import { TODO_FILTER_LOCATION_HASH, TodoFilter } from 'app/constants';
11+
12+
export const TodoContainer = observer(() => {
13+
const todoStore = useTodoStore([
14+
new TodoModel('Use MobX'),
15+
new TodoModel('Use React'),
16+
]);
17+
const history = useHistory();
18+
const location = useLocation();
19+
const [filter, setFilter] = React.useState(TodoFilter.ALL);
20+
21+
// location change callback
22+
React.useEffect(() => {
23+
console.log('effect');
24+
const nextFilter = Object.keys(TODO_FILTER_LOCATION_HASH)
25+
.map((key) => Number(key) as TodoFilter)
26+
.find((item) => TODO_FILTER_LOCATION_HASH[item] === location.hash);
27+
setFilter(nextFilter ?? TodoFilter.ALL);
28+
}, [location.hash, setFilter]);
29+
30+
// filter change callback
31+
const handleFilterChange = React.useCallback(
32+
(nextFilter: TodoFilter) => {
33+
setFilter(nextFilter);
34+
const nextHash = TODO_FILTER_LOCATION_HASH[nextFilter];
35+
history.replace(nextHash);
36+
},
37+
[history, setFilter]
38+
);
39+
40+
const itemsToDisplay =
41+
filter === TodoFilter.ALL
42+
? todoStore.todos
43+
: filter === TodoFilter.ACTIVE
44+
? todoStore.activeTodos
45+
: todoStore.completedTodos;
46+
47+
return (
48+
<div className={style.normal}>
49+
<Header addTodo={todoStore.addTodo} />
50+
<TodoList
51+
todos={itemsToDisplay}
52+
completeAll={todoStore.completeAll}
53+
deleteTodo={todoStore.deleteTodo}
54+
editTodo={todoStore.editTodo}
55+
/>
56+
<Footer
57+
filter={filter}
58+
activeCount={todoStore.activeTodos.length}
59+
completedCount={todoStore.completedTodos.length}
60+
onClearCompleted={todoStore.clearCompleted}
61+
onChangeFilter={handleFilterChange}
62+
/>
63+
</div>
64+
);
65+
});

src/app/index.tsx

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
11
import * as React from 'react';
22
import { hot } from 'react-hot-loader/root';
33
import { Router, Route, Switch } from 'react-router';
4-
import { Root } from 'app/containers/Root';
5-
import { TodoApp } from 'app/containers/TodoApp';
4+
import { TodoContainer } from 'app/containers/TodoContainer';
65

76
// render react DOM
8-
export const App = hot(({ history }) => (
9-
<Root>
7+
export const App = hot(({ history }) => {
8+
return (
109
<Router history={history}>
1110
<Switch>
12-
<Route path="/" component={TodoApp} />
11+
<Route path="/" component={TodoContainer} />
1312
</Switch>
1413
</Router>
15-
</Root>
16-
));
14+
);
15+
});

src/app/stores/RouterStore.ts

Lines changed: 0 additions & 16 deletions
This file was deleted.

0 commit comments

Comments
 (0)