Rewrite of Day 1 to use modern React (#294)

* update to hooks

* more class to function

* cleanup

* finish ts final

* update html lesson

* add lessons page

* clean up

* move getters into context

* adding type

* fix bug

* step 5 cleanup

* init final pass

* text tweak

* fix ternaries

* readme cleanup

* fixed root readme
This commit is contained in:
Micah Godbolt
2022-01-13 09:22:50 -08:00
committed by GitHub
parent 4998c158d2
commit 7cea32428e
60 changed files with 923 additions and 929 deletions
+2 -2
View File
@@ -9,6 +9,6 @@ If you don't already have the app running, start it by running `npm start` from
### TodoListItem
1. Pull in `label` and `completed` from props using [destructuring](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment#Object_destructuring)
2. Set the todo's text to `label` and the `checked` prop to `completed`
1. Pull in `label` and `status` from props using [destructuring](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment#Object_destructuring)
2. Set the `input` text to `label` and the `checked` prop to `true` if `status === 'completed`
> Note that this is only half the work we need to do to make these controlled inputs work. What is the other half?
+33 -35
View File
@@ -3,39 +3,37 @@ import { TodoFooter } from './components/TodoFooter';
import { TodoHeader } from './components/TodoHeader';
import { TodoList } from './components/TodoList';
export class TodoApp extends React.Component<any, any> {
constructor(props) {
super(props);
this.state = {
todos: {
'04': {
label: 'Todo 4',
completed: true
},
'03': {
label: 'Todo 3',
completed: false
},
'02': {
label: 'Todo 2',
completed: false
},
'01': {
label: 'Todo 1',
completed: false
}
},
filter: 'all'
};
}
render() {
const { filter, todos = [] } = this.state;
return (
<div>
<TodoHeader filter={filter} />
<TodoList todos={todos} filter={filter} />
<TodoFooter todos={todos} />
</div>
);
}
const defaultTodos = [
{
id: '04',
label: 'Todo 4',
status: 'completed',
},
{
id: '03',
label: 'Todo 3',
status: 'active',
},
{
id: '02',
label: 'Todo 2',
status: 'active',
},
{
id: '01',
label: 'Todo 1',
status: 'active',
},
];
export const TodoApp = () => {
const [filter, setFilter] = React.useState('all');
const [todos, setTodos] = React.useState(defaultTodos);
return (
<div>
<TodoHeader filter={filter} />
<TodoList todos={todos} filter={filter} />
<TodoFooter todos={todos} />
</div>
);
}
@@ -1,7 +1,7 @@
import React from 'react';
export const TodoFooter = (props: any) => {
const itemCount = Object.keys(props.todos).filter(id => !props.todos[id].completed).length;
export const TodoFooter = (props) => {
const itemCount = props.todos.filter((todo) => todo.status === 'active').length;
return (
<footer>
<span>4 items left</span>
+21 -26
View File
@@ -1,30 +1,25 @@
import React from 'react';
export class TodoHeader extends React.Component<any, any> {
constructor(props) {
super(props);
this.state = { labelInput: '' };
}
export const TodoHeader = (props) => {
const [inputText, setInputText] = React.useState<string>('');
const { filter } = props;
render() {
const { filter } = this.props;
return (
<header>
<h1>todos <small>(1.6 exercise)</small></h1>
<div className="addTodo">
<input value={this.state.labelInput} onChange={this._onChange} className="textfield" placeholder="add todo" />
<button className="submit">Add</button>
</div>
<nav className="filter">
<button className={filter === 'all' ? 'selected' : ''}>all</button>
<button className={filter === 'active' ? 'selected' : ''}>active</button>
<button className={filter === 'completed' ? 'selected' : ''}>completed</button>
</nav>
</header>
);
}
_onChange = evt => {
this.setState({ labelInput: evt.target.value });
const onInput = e => {
setInputText(e.target.value);
};
}
return (
<header>
<h1>todos <small>(1.6 exercise)</small></h1>
<div className="addTodo">
<input value={inputText} onChange={onInput} className="textfield" placeholder="add todo" />
<button className="submit">Add</button>
</div>
<nav className="filter">
<button className={filter === 'all' ? 'selected' : ''}> all</button>
<button className={filter === 'active' ? 'selected' : ''}>active</button>
<button className={filter === 'completed' ? 'selected' : ''}>completed</button>
</nav>
</header>
);
}
+16 -15
View File
@@ -1,20 +1,21 @@
import React from 'react';
import { TodoListItem } from './TodoListItem';
export class TodoList extends React.Component<any, any> {
render() {
const { filter, todos } = this.props;
export const TodoList = (props) => {
const { filter, todos } = props;
// filteredTodos returns an array of filtered todo keys [01,02,03]
const filteredTodos = Object.keys(todos).filter(id => {
return filter === 'all' || (filter === 'completed' && todos[id].completed) || (filter === 'active' && !todos[id].completed);
});
return (
<ul className="todos">
{filteredTodos.map(id => (
<TodoListItem key={id} id={id} {...todos[id]} />
))}
</ul>
);
}
const filteredTodos = todos.filter((todo) => {
if (todo.status === 'cleared') return false;
return filter === 'all' ||
(filter === 'completed' && todo.status === 'completed') ||
(filter === 'active' && todo.status === 'active');
});
return (
<ul className="todos">
{filteredTodos.map((todo) => (
<TodoListItem key={todo.id} {...todo} />
))}
</ul>
);
}
@@ -1,13 +1,11 @@
import React from 'react';
export class TodoListItem extends React.Component<any, any> {
render() {
return (
<li className="todo">
<label>
<input type="checkbox" /> Todo 1
export const TodoListItem = (props) => {
return (
<li className="todo">
<label>
<input type="checkbox" /> Todo 1
</label>
</li>
);
}
</li>
);
}