mirror of
https://github.com/microsoft/frontend-bootcamp.git
synced 2026-01-26 14:56:42 +08:00
Merge branch 'master' into day2-7
This commit is contained in:
@@ -21,5 +21,5 @@ describe('TodoApp reducers', () => {
|
|||||||
*/
|
*/
|
||||||
});
|
});
|
||||||
|
|
||||||
// TODO: test remove, complete and clear
|
// TODO: add a test for remove()
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -19,20 +19,21 @@ export function remove(state: Store['todos'], id: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function complete(state: Store['todos'], id: string) {
|
export function complete(state: Store['todos'], id: string) {
|
||||||
// Write code:
|
// Clone the todo, overriding
|
||||||
// - to clone the state[id] object into new todo object, using the spread syntax
|
const newTodo = { ...state[id], completed: !state[id].completed };
|
||||||
// - in the spread syntax, also override the value of the completed key like this: {...foo, [id]: !foo[id].completed}
|
return { ...state, [id]: newTodo };
|
||||||
// - modify new state and set the id key to the value of the new item object
|
|
||||||
|
|
||||||
return state;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function clear(state: Store['todos']) {
|
export function clear(state: Store['todos']) {
|
||||||
// Write code:
|
// Clone the todos
|
||||||
// - to clone the state object into new state object
|
const newTodos = { ...state };
|
||||||
// - loop through the keys of the new state object
|
|
||||||
// - remove those items inside that new state if the item is completed using the "delete" keyword
|
|
||||||
// - return the new state
|
|
||||||
|
|
||||||
return state;
|
// Delete all todos based on the completed flag, looping over the keys of the todos
|
||||||
|
Object.keys(state).forEach(key => {
|
||||||
|
if (state[key].completed) {
|
||||||
|
delete newTodos[key];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return newTodos;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ That's right, Redux doesn't just work with React. It can also be used with Vue.j
|
|||||||
|
|
||||||
The store doesn't magically get passed to the views. It has to be supplied by a `react-redux` component called [`<Provider>`](https://react-redux.js.org/api/provider). A `<Provider>` can be placed anywhere, but it's best to just make it available at the root the app:
|
The store doesn't magically get passed to the views. It has to be supplied by a `react-redux` component called [`<Provider>`](https://react-redux.js.org/api/provider). A `<Provider>` can be placed anywhere, but it's best to just make it available at the root the app:
|
||||||
|
|
||||||
```tsx
|
```js
|
||||||
const store = createStore(reducers);
|
const store = createStore(reducers);
|
||||||
|
|
||||||
const App = () => {
|
const App = () => {
|
||||||
@@ -32,7 +32,7 @@ const App = () => {
|
|||||||
|
|
||||||
`react-redux` provides a [`connect()`](https://react-redux.js.org/api/connect) function that turns the Redux store and dispatch functions into props for React components. The state and action dispatchers are passed along with a `<Provider>` component.
|
`react-redux` provides a [`connect()`](https://react-redux.js.org/api/connect) function that turns the Redux store and dispatch functions into props for React components. The state and action dispatchers are passed along with a `<Provider>` component.
|
||||||
|
|
||||||
```ts
|
```js
|
||||||
const OldComponent = props => {
|
const OldComponent = props => {
|
||||||
return <div>{props.foo}</div>;
|
return <div>{props.foo}</div>;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -10,7 +10,8 @@ interface TodoFooterProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const TodoFooter = (props: TodoFooterProps) => {
|
const TodoFooter = (props: TodoFooterProps) => {
|
||||||
const itemCount = Object.keys(props.todos).filter(id => !props.todos[id].completed).length;
|
const { todos } = props;
|
||||||
|
const itemCount = todos ? Object.keys(todos).filter(id => !props.todos[id].completed).length : 0;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack horizontal horizontalAlign="space-between">
|
<Stack horizontal horizontalAlign="space-between">
|
||||||
|
|||||||
@@ -4,6 +4,8 @@
|
|||||||
|
|
||||||
If you still have `npm test` running from the last step, stop it using `ctrl+C`. Start the app by running `npm start` from the root of the `frontend-bootcamp` folder. Click the "exercise" link under day 2 step 7 to see results.
|
If you still have `npm test` running from the last step, stop it using `ctrl+C`. Start the app by running `npm start` from the root of the `frontend-bootcamp` folder. Click the "exercise" link under day 2 step 7 to see results.
|
||||||
|
|
||||||
|
At the beginning of this exercise, the "Add" and "Clear Completed" buttons do not work. We'll be fixing that in this step!
|
||||||
|
|
||||||
1. Open `exercise/src/index.tsx` and wrap `<TodoApp>` with `<Provider>` as instructed in the comment
|
1. Open `exercise/src/index.tsx` and wrap `<TodoApp>` with `<Provider>` as instructed in the comment
|
||||||
|
|
||||||
2. Open `exercise/src/components/TodoFooter.tsx` and erase the "nullable" type modifier (i.e. the ?) in the interface definition of `TodoFooterProps`
|
2. Open `exercise/src/components/TodoFooter.tsx` and erase the "nullable" type modifier (i.e. the ?) in the interface definition of `TodoFooterProps`
|
||||||
|
|||||||
@@ -11,7 +11,8 @@ interface TodoFooterProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const TodoFooter = (props: TodoFooterProps) => {
|
export const TodoFooter = (props: TodoFooterProps) => {
|
||||||
const itemCount = Object.keys(props.todos).filter(id => !props.todos[id].completed).length;
|
const { todos } = props;
|
||||||
|
const itemCount = todos ? Object.keys(todos).filter(id => !props.todos[id].completed).length : 0;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack horizontal horizontalAlign="space-between">
|
<Stack horizontal horizontalAlign="space-between">
|
||||||
|
|||||||
@@ -15,5 +15,10 @@ store.dispatch(actions.addTodo('world'));
|
|||||||
|
|
||||||
initializeIcons();
|
initializeIcons();
|
||||||
|
|
||||||
// TODO: wrap <TodoApp> with a <Provider store={store}> instance here
|
// TODO: see how we added Provider is the root element
|
||||||
ReactDOM.render(<TodoApp />, document.getElementById('app'));
|
ReactDOM.render(
|
||||||
|
<Provider store={store}>
|
||||||
|
<TodoApp />
|
||||||
|
</Provider>,
|
||||||
|
document.getElementById('app')
|
||||||
|
);
|
||||||
|
|||||||
@@ -10,7 +10,8 @@ interface TodoFooterProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const TodoFooter = (props: TodoFooterProps) => {
|
const TodoFooter = (props: TodoFooterProps) => {
|
||||||
const itemCount = Object.keys(props.todos).filter(id => !props.todos[id].completed).length;
|
const { todos } = props;
|
||||||
|
const itemCount = todos ? Object.keys(todos).filter(id => !props.todos[id].completed).length : 0;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack horizontal horizontalAlign="space-between">
|
<Stack horizontal horizontalAlign="space-between">
|
||||||
|
|||||||
Reference in New Issue
Block a user