Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update docs to improve readability #3476

Merged
merged 1 commit into from
Jul 16, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 12 additions & 12 deletions docs/advanced/AsyncActions.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ function receivePosts(subreddit, json) {
This is all we need to know for now. The particular mechanism to dispatch these actions together with network requests will be discussed later.

> ##### Note on Error Handling

>
> In a real app, you'd also want to dispatch an action on request failure. We won't implement error handling in this tutorial, but the [real world example](../introduction/Examples.md#real-world) shows one of the possible approaches.

## Designing the State Shape
Expand Down Expand Up @@ -163,11 +163,11 @@ There are a few important bits here:
- For every list of items, you'll want to store `isFetching` to show a spinner, `didInvalidate` so you can later toggle it when the data is stale, `lastUpdated` so you know when it was fetched the last time, and the `items` themselves. In a real app, you'll also want to store pagination state like `fetchedPageCount` and `nextPageUrl`.

> ##### Note on Nested Entities

>
> In this example, we store the received items together with the pagination information. However, this approach won't work well if you have nested entities referencing each other, or if you let the user edit items. Imagine the user wants to edit a fetched post, but this post is duplicated in several places in the state tree. This would be really painful to implement.

>
> If you have nested entities, or if you let users edit received entities, you should keep them separately in the state as if it was a database. In pagination information, you would only refer to them by their IDs. This lets you always keep them up to date. The [real world example](../introduction/Examples.md#real-world) shows this approach, together with [normalizr](https://github.com/paularmstrong/normalizr) to normalize the nested API responses. With this approach, your state might look like this:

>
> ```js
> {
> selectedSubreddit: 'frontend',
Expand Down Expand Up @@ -206,15 +206,15 @@ There are a few important bits here:
> }
> }
> ```

>
> In this guide, we won't normalize entities, but it's something you should consider for a more dynamic application.

## Handling Actions

Before going into the details of dispatching actions together with network requests, we will write the reducers for the actions we defined above.

> ##### Note on Reducer Composition

>
> Here, we assume that you understand reducer composition with [`combineReducers()`](../api/combineReducers.md), as described in the [Splitting Reducers](../basics/Reducers.md#splitting-reducers) section on the [basics guide](../basics/README.md). If you don't, please [read it first](../basics/Reducers.md#splitting-reducers).

#### `reducers.js`
Expand Down Expand Up @@ -390,18 +390,18 @@ export function fetchPosts(subreddit) {
```

> ##### Note on `fetch`

>
> We use [`fetch` API](https://developer.mozilla.org/en/docs/Web/API/Fetch_API) in the examples. It is a new API for making network requests that replaces `XMLHttpRequest` for most common needs. Because most browsers don't yet support it natively, we suggest that you use [`cross-fetch`](https://github.com/lquixada/cross-fetch) library:

>
> ```js
> // Do this in every file where you use `fetch`
> import fetch from 'cross-fetch'
> ```

>
> Internally, it uses [`whatwg-fetch` polyfill](https://github.com/github/fetch) on the client, and [`node-fetch`](https://github.com/bitinn/node-fetch) on the server, so you won't need to change API calls if you change your app to be [universal](https://medium.com/@mjackson/universal-javascript-4761051b7ae9).

>
> Be aware that any `fetch` polyfill assumes a [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) polyfill is already present. The easiest way to ensure you have a Promise polyfill is to enable Babel's ES6 polyfill in your entry point before any other code runs:

>
> ```js
> // Do this once before any other code in your app
> import 'babel-polyfill'
Expand Down Expand Up @@ -515,7 +515,7 @@ store
```

> ##### Note about Server Rendering

>
> Async action creators are especially convenient for server rendering. You can create a store, dispatch a single async action creator that dispatches other async action creators to fetch data for a whole section of your app, and only render after the Promise it returns, completes. Then your store will already be hydrated with the state you need before rendering.

[Thunk middleware](https://github.com/gaearon/redux-thunk) isn't the only way to orchestrate asynchronous actions in Redux:
Expand Down
2 changes: 1 addition & 1 deletion docs/advanced/Middleware.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ How do we approach this with Redux?
The most naïve solution is just to log the action and the next state yourself every time you call [`store.dispatch(action)`](../api/Store.md#dispatch). It's not really a solution, but just a first step towards understanding the problem.

> ##### Note

>
> If you're using [react-redux](https://github.com/reduxjs/react-redux) or similar bindings, you likely won't have direct access to the store instance in your components. For the next few paragraphs, just assume you pass the store down explicitly.

Say, you call this when creating a todo:
Expand Down
6 changes: 3 additions & 3 deletions docs/advanced/UsageWithReactRouter.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ So you want to do routing with your Redux app. You can use it with [React Router
Before integrating React Router, we need to configure our development server. Indeed, our development server may be unaware of the declared routes in React Router configuration. For example, if you access `/todos` and refresh, your development server needs to be instructed to serve `index.html` because it is a single-page app. Here's how to enable this with popular development servers.

> ### Note on Create React App

>
> If you are using Create React App, you won't need to configure a fallback URL, it is automatically done.

### Configuring Express
Expand Down Expand Up @@ -221,7 +221,7 @@ const App = ({ match: { params } }) => {
Now that you know how to do basic routing, you can learn more about [React Router API](https://reacttraining.com/react-router/)

> ##### Note About Other Routing Libraries

>
> _Redux Router_ is an experimental library, it lets you keep entirely the state of your URL inside your redux store. It has the same API with React Router API but has a smaller community support than react-router.

>
> _React Router Redux_ creates a binding between your redux app and react-router and it keeps them in sync. Without this binding, you will not be able to rewind the actions with Time Travel. Unless you need this, React Router and Redux can operate completely apart.
4 changes: 2 additions & 2 deletions docs/api/Store.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ A store is not a class. It's just an object with a few methods on it.
To create it, pass your root [reducing function](../Glossary.md#reducer) to [`createStore`](createStore.md).

> ##### A Note for Flux Users

>
> If you're coming from Flux, there is a single important difference you need to understand. Redux doesn't have a Dispatcher or support many stores. **Instead, there is just a single store with a single root [reducing function](../Glossary.md#reducer).** As your app grows, instead of adding stores, you split the root reducer into smaller reducers independently operating on the different parts of the state tree. You can use a helper like [`combineReducers`](combineReducers.md) to combine them. This is similar to how there is just one root component in a React app, but it is composed out of many small components.

### Store Methods
Expand Down Expand Up @@ -46,7 +46,7 @@ The store's reducing function will be called with the current [`getState()`](#ge
> ##### A Note for Flux Users
>
> If you attempt to call `dispatch` from inside the [reducer](../Glossary.md#reducer), it will throw with an error saying “Reducers may not dispatch actions.” This is similar to “Cannot dispatch in a middle of dispatch” error in Flux, but doesn't cause the problems associated with it. In Flux, a dispatch is forbidden while Stores are handling the action and emitting updates. This is unfortunate because it makes it impossible to dispatch actions from component lifecycle hooks or other benign places.

>
> In Redux, subscriptions are called after the root reducer has returned the new state, so you _may_ dispatch in the subscription listeners. You are only disallowed to dispatch inside the reducers because they must have no side effects. If you want to cause a side effect in response to an action, the right place to do this is in the potentially async [action creator](../Glossary.md#action-creator).

#### Arguments
Expand Down
2 changes: 1 addition & 1 deletion docs/api/combineReducers.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ You can control state key names by using different keys for the reducers in the
A popular convention is to name reducers after the state slices they manage, so you can use ES6 property shorthand notation: `combineReducers({ counter, todos })`. This is equivalent to writing `combineReducers({ counter: counter, todos: todos })`.

> ##### A Note for Flux Users

>
> This function helps you organize your reducers to manage their own slices of state, similar to how you would have different Flux Stores to manage different state. With Redux, there is just one store, but `combineReducers` helps you keep the same logical division between reducers.

#### Arguments
Expand Down
2 changes: 1 addition & 1 deletion docs/basics/Actions.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import { ADD_TODO, REMOVE_TODO } from '../actionTypes'
```

> ##### Note on Boilerplate

>
> You don't have to define action type constants in a separate file, or even to define them at all. For a small project, it might be easier to just use string literals for action types. However, there are some benefits to explicitly declaring constants in larger codebases. Read [Reducing Boilerplate](../recipes/ReducingBoilerplate.md) for more practical tips on keeping your codebase clean.

Other than `type`, the structure of an action object is really up to you. If you're interested, check out [Flux Standard Action](https://github.com/acdlite/flux-standard-action) for recommendations on how actions could be constructed.
Expand Down
12 changes: 6 additions & 6 deletions docs/basics/Reducers.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ You'll often find that you need to store some data, as well as some UI state, in
```

> ##### Note on Relationships

>
> In a more complex app, you're going to want different entities to reference each other. We suggest that you keep your state as normalized as possible, without any nesting. Keep every entity in an object stored with an ID as a key, and use IDs to reference it from other entities, or lists. Think of the app's state as a database. This approach is described in [normalizr's](https://github.com/paularmstrong/normalizr) documentation in detail. For example, keeping `todosById: { id -> todo }` and `todos: array<id>` inside the state would be a better idea in a real app, but we're keeping the example simple.

## Handling Actions
Expand Down Expand Up @@ -111,13 +111,13 @@ Note that:
2. **We return the previous `state` in the `default` case.** It's important to return the previous `state` for any unknown action.

> ##### Note on `Object.assign`

>
> [`Object.assign()`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/assign) is a part of ES6, and is not supported by older browsers. To support them, you will need to either use a polyfill, a [Babel plugin](https://www.npmjs.com/package/babel-plugin-transform-object-assign), or a helper from another library like [`_.assign()`](https://lodash.com/docs#assign).

> ##### Note on `switch` and Boilerplate

>
> The `switch` statement is _not_ the real boilerplate. The real boilerplate of Flux is conceptual: the need to emit an update, the need to register the Store with a Dispatcher, the need for the Store to be an object (and the complications that arise when you want a universal app). Redux solves these problems by using pure reducers instead of event emitters.

>
> It's unfortunate that many still choose a framework based on whether it uses `switch` statements in the documentation. If you don't like `switch`, you can use a custom `createReducer` function that accepts a handler map, as shown in [“reducing boilerplate”](../recipes/ReducingBoilerplate.md#reducers).

## Handling More Actions
Expand Down Expand Up @@ -379,9 +379,9 @@ function reducer(state = {}, action) {
All [`combineReducers()`](../api/combineReducers.md) does is generate a function that calls your reducers **with the slices of state selected according to their keys**, and combines their results into a single object again. [It's not magic.](https://github.com/reduxjs/redux/issues/428#issuecomment-129223274) And like other reducers, `combineReducers()` does not create a new object if all of the reducers provided to it do not change state.

> ##### Note for ES6 Savvy Users

>
> Because `combineReducers` expects an object, we can put all top-level reducers into a separate file, `export` each reducer function, and use `import * as reducers` to get them as an object with their names as the keys:

>
> ```js
> import { combineReducers } from 'redux'
> import * as reducers from './reducers'
Expand Down
2 changes: 1 addition & 1 deletion docs/faq/General.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,5 +94,5 @@ Redux can be used as a data store for any UI layer. The most common usage is wit
Redux is originally written in ES6 and transpiled for production into ES5 with Webpack and Babel. You should be able to use it regardless of your JavaScript build process. Redux also offers a UMD build that can be used directly without any build process at all. The [counter-vanilla](https://github.com/reduxjs/redux/tree/master/examples/counter-vanilla) example demonstrates basic ES5 usage with Redux included as a `<script>` tag. As the relevant pull request says:

> The new Counter Vanilla example is aimed to dispel the myth that Redux requires Webpack, React, hot reloading, sagas, action creators, constants, Babel, npm, CSS modules, decorators, fluent Latin, an Egghead subscription, a PhD, or an Exceeds Expectations O.W.L. level.

>
> Nope, it's just HTML, some artisanal `<script>` tags, and plain old DOM manipulation. Enjoy!