Skip to content

Commit

Permalink
Remove folded sourcecode. Use one combined CodeSandbox sourecode for …
Browse files Browse the repository at this point in the history
…the UI components + unconnected Redux store code sample. (#1022)
  • Loading branch information
wgao19 authored and markerikson committed Sep 18, 2018
1 parent 5876977 commit 1ad1667
Showing 1 changed file with 3 additions and 340 deletions.
343 changes: 3 additions & 340 deletions docs/GettingStarted.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Getting Started

[React-Redux](https://github.com/reduxjs/react-redux) is the official [React](https://reactjs.org/) binding for [Redux](https://redux.js.org/). It lets your React components read data from a Redux store, and dispatch actions to the store to update data.
[React-Redux](https://github.com/reduxjs/react-redux) is the official [React](https://reactjs.org/) binding for [Redux](https://redux.js.org/). It lets your React components read data from a Redux store, and dispatch actions to the store to update data.

## Installation

Expand Down Expand Up @@ -110,180 +110,6 @@ We have implemented our React UI components as follows:
- `constants` holds the constants data for our app.
- And finally `index` renders our app to the DOM.

You may check out the sourcecode below or check out this CodeSandbox: [Todo App UI Only](https://codesandbox.io/s/mo7p88po0j).

<details>
<summary>Expand Code</summary>

```
// tree structure
.
├── components
│ ├── AddTodo.js
│ ├── TodoList.js
│ ├── Todo.js
│ └── VisibilityFilters.js
├── TodoApp.js
├── constants.js
└── index.js
```

```jsx
// TodoApp.js
import React from "react";
import AddTodo from "./components/AddTodo";
import TodoList from "./components/TodoList";
import VisibilityFilters from "./components/VisibilityFilters";

export default function TodoApp() {
return (
<div className="todo-app">
<h1>Todo List</h1>
<AddTodo />
<TodoList />
<VisibilityFilters />
</div>
);
}
```

```jsx
// components/AddTodo.js

import React from "react";

class AddTodo extends React.Component {
constructor(props) {
super(props);
this.state = { input: "" };
}

updateInput = input => {
this.setState({ input });
};

handleAddTodo = () => {
// dispatches actions to add todo
// sets state back to empty string
};

render() {
return (
<div>
<input
onChange={e => this.updateInput(e.target.value)}
value={this.state.input}
/>
<button className="add-todo" onClick={this.handleAddTodo}>
Add Todo
</button>
</div>
);
}
}

export default AddTodo;
```

```jsx
// components/Todo.js

import React from "react";
import cx from "classnames";

const Todo = ({ todo }) => (
<li
className="todo-item"
onClick={() => {} /** dispatches action to toggle todo */}
>
{todo && todo.completed ? "👌" : "👋"}{" "}
<span
className={cx(
"todo-item__text",
todo && todo.completed && "todo-item__text--completed"
)}
>
{todo.content}
</span>
</li>
);

export default Todo;
```

```jsx
// components/TodoList.js

import React from "react";
import Todo from "./Todo";

const TodoList = ({ todos }) => (
<ul className="todo-list">
{todos && todos.length
? todos.map((todo, index) => {
return <Todo key={`todo-${todo.id}`} todo={todo} />;
})
: "No todos, yay!"}
</ul>
);

export default TodoList;
```

```jsx
// components/VisibilityFilters.js

import React from "react";
import cx from "classnames";
import { VISIBILITY_FILTERS } from "../constants";

const VisibilityFilters = ({ activeFilter }) => {
return (
<div className="visibility-filters">
{Object.keys(VISIBILITY_FILTERS).map(filterKey => {
const currentFilter = VISIBILITY_FILTERS[filterKey];
return (
<span
key={`visibility-filter-${currentFilter}`}
className={cx(
"filter",
currentFilter === activeFilter && "filter--active"
)}
onClick={() => {} /** dispatches action to set filter */}
>
{currentFilter}
</span>
);
})}
</div>
);
};

export default VisibilityFilters;
```

```JavaScript
// constants.js
export const VISIBILITY_FILTERS = {
ALL: "all",
COMPLETED: "completed",
INCOMPLETE: "incomplete"
};
```

```jsx
// index.js
import React from "react";
import ReactDOM from "react-dom";

import TodoApp from "./TodoApp";

const rootElement = document.getElementById("root");
ReactDOM.render(<TodoApp />, rootElement);
```

</details>

<br />

**The Redux Store**
Expand All @@ -310,170 +136,7 @@ The Redux portion of the application has been set up using the [patterns recomme
- `getTodos` is slightly more complex. It takes all the `id`s from `allIds`, finds each todo in `byIds`, and returns the final array of todos
- `getTodosByVisibilityFilter` filters the todos according to the visibility filter

Once again you may expand the code below or check out this CodeSandbox here: [Todo App (UI + Unconnected Redux)](https://codesandbox.io/s/6vwyqrpqk3).

<details>
<summary>Expand Code</summary>

```
.
└── redux
├── reducers
│ ├── index.js
│ ├── todos.js
│ └── visibilityFilters.js
├── actionTypes.js
├── actions.js
├── selectors.js
└── store.js
```

```JavaScript
// redux/store.js
import { createStore } from "redux";
import rootReducer from "./reducers";

export default createStore(rootReducer);
```

```JavaScript
// redux/reducers/index.js
import { combineReducers } from "redux";
import todoList from "./todoList";
import todoMap from "./todoMap";
import visibilityFilter from "./visibilityFilter";

export default combineReducers({ todoList, todoMap, visibilityFilter });
```

```JavaScript
// redux/reducers/todos.js
import { ADD_TODO, TOGGLE_TODO } from "../actionTypes";

const initialState = {
allIds: [],
byIds: {}
};

export default function(state = initialState, action) {
switch (action.type) {
case ADD_TODO: {
const { id, content } = action.payload;
return {
...state,
allIds: [...state.allIds, id],
byIds: {
...state.byIds,
[id]: {
content,
completed: false
}
}
};
}
case TOGGLE_TODO: {
const { id } = action.payload;
return {
...state,
byIds: {
...state.byIds,
[id]: {
...state.byIds[id],
completed: !state.byIds[id].completed
}
}
};
}
default:
return state;
}
}
```

```JavaScript
// redux/reducers/visibilityFilter.js
import { SET_FILTER } from "../actionTypes";
import { VISIBILITY_FILTERS } from "../../constants";

const defaultState = VISIBILITY_FILTERS.ALL;

const visibilityFilter = (state = defaultState, action) => {
switch (action.type) {
case SET_FILTER: {
return action.payload.filter;
}
default: {
return state;
}
}
};

export default visibilityFilter;
```

```JavaScript
// redux/actions.js
import { ADD_TODO, TOGGLE_TODO, SET_FILTER } from "./actionTypes";

let nextTodoId = 0;

export const addTodo = content => ({
type: ADD_TODO,
payload: {
id: ++nextTodoId,
content
}
});

export const toggleTodo = id => ({
type: TOGGLE_TODO,
payload: { id }
});

export const setFilter = filter => ({ type: SET_FILTER, payload: { filter } });
```

```JavaScript
// redux/selectors.js
import { VISIBILITY_FILTERS } from "../constants";

export const getTodosState = store => store.todos;

export const getTodoList = store =>
getTodosState(store) ? getTodosState(store).allIds : [];

export const getTodoById = (store, id) =>
getTodoState(store) ? { ...getTodosState(store).byIds[id], id } : {};

export const getTodos = store =>
getTodoList(store).map(id => getTodoById(store, id));

/**
* example of a slightly more complex selector
* select from store combining information from multiple reducers
*/
export const getTodosByVisibilityFilter = (store, visibilityFilter) => {
const allTodos = getTodos(store);
switch (visibilityFilter) {
case VISIBILITY_FILTERS.COMPLETED:
return allTodos.filter(todo => todo.completed);
case VISIBILITY_FILTERS.INCOMPLETE:
return allTodos.filter(todo => !todo.completed);
case VISIBILITY_FILTERS.ALL:
default:
return allTodos;
}
};
```

```JavaScript
// redux/actionTypes.js
export const ADD_TODO = "ADD_TODO";
export const TOGGLE_TODO = "TOGGLE_TODO";
export const SET_FILTER = "SET_FILTER";
```

</details>
You may check out [this CodeSandbox](https://codesandbox.io/s/6vwyqrpqk3) for the source code of the UI components and the unconnected Redux store described above.

<br />

Expand Down Expand Up @@ -660,7 +323,7 @@ const TodoList = // ... UI component implementation
export default connect(state => ({ todos: getTodos(state) }))(TodoList);
```

We recommend encapsulating any complex lookups or computations of data in selector functions. In addition, you can further optimize the performance by using [Reselect](https://github.com/reduxjs/reselect) to write “memoized” selectors that can skip unnecessary work. (See [the Redux docs page on Computing Derived Data](https://redux.js.org/recipes/computingderiveddata#sharing-selectors-across-multiple-components) and the blog post [Idiomatic Redux: Using Reselect Selectors for Encapsulation and Performance](https://blog.isquaredsoftware.com/2017/12/idiomatic-redux-using-reselect-selectors/) for more information on why and how to use selector functions.)
We recommend encapsulating any complex lookups or computations of data in selector functions. In addition, you can further optimize the performance by using [Reselect](https://github.com/reduxjs/reselect) to write “memoized” selectors that can skip unnecessary work. (See [the Redux docs page on Computing Derived Data](https://redux.js.org/recipes/computingderiveddata#sharing-selectors-across-multiple-components) and the blog post [Idiomatic Redux: Using Reselect Selectors for Encapsulation and Performance](https://blog.isquaredsoftware.com/2017/12/idiomatic-redux-using-reselect-selectors/) for more information on why and how to use selector functions.)

Now that our `<TodoList />` is connected to the store. It should receive the list of todos, map over them, and pass each todo to the `<Todo />` component. `<Todo />` will in turn render them to the screen. Now try adding a todo. It should come up on our todo list!

Expand Down

0 comments on commit 1ad1667

Please sign in to comment.