Skip to content

Commit

Permalink
Updated docs, documented feature branches, added recipes
Browse files Browse the repository at this point in the history
  • Loading branch information
langpavel committed Apr 26, 2016
1 parent c948d5d commit 879693f
Show file tree
Hide file tree
Showing 5 changed files with 199 additions and 0 deletions.
1 change: 1 addition & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ forked repo, check that it meets these guidelines:
* [Squash](http://stackoverflow.com/questions/5189560/squash-my-last-x-commits-together-using-git)
your commits into one for each PR.
* Run `npm test` to make sure that your code style is OK and there are no any regression bugs.
* If you contributing to opt-in feature, prefix your PR title with `[feature/...]` tag.

#### Style Guide

Expand Down
17 changes: 17 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,23 @@ expenses via [OpenCollective](https://opencollective.com/react-starter-kit) or
<img src="https://opencollective.com/static/images/become_backer.svg" width="64" height="64" alt="">
</a>

### Feature branches

There are feature branches.
You can just merge and it will give you desired functionality.
These branches should be in sync with master and themselves so there should not be merging conflicts. If not, please report it.

* [feature/redux](https://github.com/kriasoft/react-starter-kit/tree/feature/redux) – isomorphic redux support.
Use [`connect()`](https://github.com/reactjs/react-redux/blob/master/docs/api.md#connectmapstatetoprops-mapdispatchtoprops-mergeprops-options)
higher order component to access state in redux store and to get actions mapped on dispatch.
You can see [LanguageSwitcher](https://github.com/kriasoft/react-starter-kit/blob/86eadfd3d11d804cf858aa21f657022fcc098752/src/components/LanguageSwitcher/LanguageSwitcher.js) component how to use `connect()`
<br/>
[Read full recipe](./docs/recipes/feature-redux.md)

* [feature/react-intl](https://github.com/kriasoft/react-starter-kit/tree/feature/react-intl)[`react-intl`](https://github.com/yahoo/react-intl#react-intl) integration based on `feature/redux`
<br/>
[Read full recipe](./docs/recipes/feature-react-intl.md)

### Learn More

* [Getting Started with React.js](http://facebook.github.io/react/)
Expand Down
2 changes: 2 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,6 @@
### Recipes

* [How to Implement Routing and Navigation](./recipes/how-to-implement-routing.md)
* [How to Integrate Redux](./recipes/feature-redux.md)
* [How to Integrate React-Intl](./recipes/feature-react-intl.md)
* [How to Integrate Disqus](./recipes/how-to-integrate-disqus.md)
121 changes: 121 additions & 0 deletions docs/recipes/feature-react-intl.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
## Integrating [React-Intl](https://github.com/yahoo/react-intl#react-intl)

1. Merge `feature/react-intl` branch with git.
You will get `feature/redux` too because this is based on top of it.

2. Adjust `INTL_REQUIRE_DESCRIPTIONS` constant in `tools/webpack.config.js` around line 17:
```js
const INTL_REQUIRE_DESCRIPTIONS = true;
```
It's boolean. When enabled, build will fail if `description` is not provided.
3. Adjust `locales` settings in `src/config.js`:
```js
// default locale is the first one
export const locales = ['en-GB', 'cs-CZ'];
```
Note that you should follow
[BCP 47](https://tools.ietf.org/html/bcp47)
([RFC 5646](https://tools.ietf.org/html/rfc5646)).
4. Add locale support in `src/client.js`:
```js
import en from 'react-intl/locale-data/en';
import cs from 'react-intl/locale-data/cs';
...
[en, cs].forEach(addLocaleData);
```
5. Execute `npm run extractMessages` or `npm start` to strip out messages.
Message files are created in `src/messages` directory.
6. Edit `src/messages/*.json` files, change only `message` property.
7. Execute `npm run build`,
your translations should be copied to `build/messages/` directory.
## How to write localizable components
Just import appropriate [component](https://github.com/yahoo/react-intl/wiki#the-react-intl-module) from `react-intl`
- For localizable text use
[`<FormattedMessage>`](https://github.com/yahoo/react-intl/wiki/Components#formattedmessage).
- You can also use it with
[`defineMessages()`](https://github.com/yahoo/react-intl/wiki/API#definemessages) helper.
- For date and time:
[`<FormattedDate>`](https://github.com/yahoo/react-intl/wiki/Components#formatteddate)
[`<FormattedTime>`](https://github.com/yahoo/react-intl/wiki/Components#formattedtime)
[`<FormattedRelative>`](https://github.com/yahoo/react-intl/wiki/Components#formattedrelative)
- For numbers and currencies:
[`<FormattedNumber>`](https://github.com/yahoo/react-intl/wiki/Components#formattednumber)
[`<FormattedPlural>`](https://github.com/yahoo/react-intl/wiki/Components#formattedplural)
- Do not use `<FormattedHTMLMessage>` if possible, see how to use *Rich Text Formatting* with
[`<FormattedMessage>`](https://github.com/yahoo/react-intl/wiki/Components#formattedmessage)
- When you need imperative formatting API, use [`injectIntl`](https://github.com/yahoo/react-intl/wiki/API#injectintl) High-Order Component.
### Example
```jsx
import { defineMessages, FormattedMessage, injectIntl, intlShape } from 'react-intl';
const messages = defineMessages({
text: {
id: 'example.text',
defaultMessage: 'Example text',
description: 'Hi Pavel',
},
textTemplate: {
id: 'example.text.template',
defaultMessage: 'Example text template',
description: 'Hi {name}',
},
});
function Example(props) {
const text = props.intl.formatMessage(messages.textTemplate, { name: 'Pavel'});
return (
<div>
<FormattedMessage
id="example.text.inlineDefinition"
defaultMessage="Hi Pavel"
description="Example of usage without defineMessages"
/>
<FormattedMessage {...messages.text} />
<FormattedMessage
{...messages.textTemplate}
values={{
name: <b>Pavel</b>
}}
/>
</div>
);
}
Example.propTypes = {
intl: intlShape,
}
export default injectIntl(Example);
```
## Updating translations
When developing, every source file is watched and parsed for messages on change.
Messages files are updated on the fly.
If new definition is found, this definition is added at the end of every used `src/messages/xx-XX.json` file so when commiting, new translations are at the tail of file.
When untranslated message is removed and if it's `message` field is empty too, message is deleted from all translation files. This is reason why `files` array is present.

When developing and you edit translation file, it should be copied to `build/messages/` directory.

## Other references

* [`Intl documentation on MDN`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Intl)
* [express-request-language](https://github.com/tinganho/express-request-language#readme)
for more details how initial language negotiation works.
58 changes: 58 additions & 0 deletions docs/recipes/feature-redux.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
## Integrating [Redux](http://redux.js.org/index.html)

Merge `feature/redux` branch with git.
If you are interrested into `feature/react-intl`,
merge that branch instead.
It contains this implementation of redux

**If you don't know redux well, you should [read about it first](http://redux.js.org/docs/basics/index.html).**


## Creating Actions

1. Go to `src/constants/index.js` and define action name there.

2. Go to `src/actions/` and create file with appropriate name.
You can copy `src/actions/runtime.js` as a template.

3. If you need async action, [`redux-thunk`](https://github.com/gaearon/redux-thunk#readme)
is there for you.
For inspiration how to create async actions you can look at
[`setLocale`](https://github.com/kriasoft/react-starter-kit/blob/feature/react-intl/src/actions/intl.js)
action from `feature/react-intl`.
See [Async Flow](http://redux.js.org/docs/advanced/AsyncFlow.html) for more on this topic


## Creating Reducer (aka Store)

1. Go to [`src/reducers/`](https://github.com/kriasoft/react-starter-kit/tree/feature/redux/src/reducers) and create new file there.

You can copy [`src/reducers/runtime.js`](https://github.com/kriasoft/react-starter-kit/tree/feature/redux/src/reducers/runtime.js) as a template.

- Do not forget to always return `state`.
- Never mutate provided `state`.
If you mutate state, rendering of connected component will not be triggered because of `===` equality.
Always return new value if you perform state update.
You can use this construct: `{ ...state, updatedKey: action.payload.value, }`
- Keep in mind that store state *must* be repeatable by replaying actions on it.
For example, when you store timestamp, pass it into *action payload*.
If you call REST API, do it in action. Never do this things in reducer!

2. Edit [`src/reducers/index.js`](https://github.com/kriasoft/react-starter-kit/tree/feature/redux/src/reducers/index.js), import your reducer and add it to root reducer created by
[`combineReducers`](http://redux.js.org/docs/api/combineReducers.html)


## Connecting Components

You can use [`connect()`](https://github.com/reactjs/react-redux/blob/master/docs/api.md#connectmapstatetoprops-mapdispatchtoprops-mergeprops-options) High-Order Component from [`react-redux`](https://github.com/reactjs/react-redux#readme) package.

See [Usage With React](http://redux.js.org/docs/basics/UsageWithReact.html) on redux.js.org.

For example you can look at
[`<LanguageSwitcher>`](https://github.com/kriasoft/react-starter-kit/blob/feature/react-intl/src/components/LanguageSwitcher/LanguageSwitcher.js)
component from `feature/react-intl` branch. It demonstrates both, subscribing to store and dispathing actions.


## Dispatching Actions On Server

See source of `src/server.js`

0 comments on commit 879693f

Please sign in to comment.