Skip to content

Commit d87a6bb

Browse files
Merge pull request #2 from ui-router/react-tutorials
React hello solar system tutorial
2 parents 2b48c04 + da5b2cb commit d87a6bb

File tree

2 files changed

+149
-1
lines changed

2 files changed

+149
-1
lines changed

_react/about.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ permalink: /react/
99
{% include toc icon="columns" title="React" %}
1010

1111
<center>
12-
<img src="/images/logos/react.png">
12+
<img src="/images/logos/react.png" width="150">
1313
</center>
1414

1515
UI-Router provides extremely flexible, state based routing to the React ecosystem.

_tutorial_react/hellosolarsystem.md

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
---
2+
title: "UI-Router for React - Hello Solar System!"
3+
excerpt: "Learn about parameters and resolve data"
4+
---
5+
{% include toc icon="columns" title="Hello Solar System!" %}
6+
7+
In this tutorial, we will build on [Hello World!](helloworld) and create a slightly more ambitious _Hello Solar System_ app.
8+
9+
We will implement a [list/detail interface](https://en.wikipedia.org/wiki/Master%E2%80%93detail_interface),
10+
also known as master-detail.
11+
To accomplish this, we will create two new application states:
12+
13+
- The `people` state will show a list of all the people.
14+
- The `person` state will show details for a specific person.
15+
16+
At any time, the user can click "reload plunker", and the app will restart at the same URL.
17+
The URL contains the information necessary to restore the application's state.
18+
When the app is restarted, it will be in the same state as before.
19+
{: .notice--info}
20+
21+
Plunker embeds can time out.
22+
If you get a "Not Found" response, your plunker embed has timed out.
23+
Click the "Refresh" icon to get a new plunker, then try experimenting with the "reload plunker" button again.
24+
{: .notice--info}
25+
26+
## Live demo
27+
28+
Take a look at the completed Hello Solar System live demo below.
29+
Click the `UISref` wrapped "People" to view the list of all people.
30+
Click a person to view the person details.
31+
32+
As you navigate through the app, the [UI-Router State Visualizer](https://github.com/ui-router/visualizer) shows
33+
the current state
34+
{: .notice--info}
35+
36+
<iframe style="width: 100%; height: 450px;" src="//embed.plnkr.co/3qSxCVrm1KuDTVH9nHjO/?show=preview" frameborder="1" allowfullscren="allowfullscren"></iframe>
37+
38+
<br>
39+
40+
# New concepts
41+
42+
This app introduces some new concepts and UI-Router features.
43+
44+
- [Resolve data](#resolve-data)
45+
- [State Parameters](#state-parameters)
46+
- [Linking with params](#linking-with-params)
47+
48+
## Resolve data
49+
50+
When a user switches back and forth between states of a single page web
51+
app, the app often needs to fetch application data from a server API,
52+
such as a REST endpoint.
53+
54+
A state can specify the data it requires by defining a `resolve:` property.
55+
When the user tries to activate a state which has a `resolve:` property,
56+
UI-Router will fetch the required data *before activating the state*.
57+
The fetched data is then passed via props to the component(s).
58+
59+
The `resolve:` property on a state definition is an array.
60+
Each element of the array is an object which defines some data to be fetched.
61+
The object has the Dependency Injection `token` (name) for the data being loaded.
62+
It has a `resolveFn` which returns a promise for the data.
63+
It also has a `deps` property, used to define the DI tokens for the `resolveFn`'s dependencies (function parameters).
64+
{: .notice--info}
65+
66+
The `resolve` property of the `people` state is an array containing a single object.
67+
The object defines how to fetch the `people` data, and assigns it a DI `token` (its name).
68+
69+
```js
70+
resolve: [{
71+
token: 'people',
72+
resolveFn: () => PeopleService.getAllPeople()
73+
}]
74+
```
75+
76+
The object defines a `resolveFn` which returns a promise for all the people data.
77+
The data is assigned a DI `token` of `'people'`.
78+
{: .notice--info}
79+
80+
When fetching data, we recommend delegating to services which return promises.
81+
{: .notice--info}
82+
83+
UI-Router waits until the promise returned from `PeopleService.getAllPeople()` resolves before activating the `people` state.
84+
The `People` component is created, and the list of people is passed to the component via its `props`.
85+
86+
```js
87+
People.propTypes = {
88+
resolves: PropTypes.shape({
89+
people: PropTypes.arrayOf(PropTypes.object)
90+
})
91+
}
92+
```
93+
94+
95+
## State Parameters
96+
97+
We also want to allow the user to be able view the details for a specific person.
98+
The `person` state takes a `personId` parameter, and uses it to fetch that specific person's details.
99+
100+
The parameter value is included as a part of the URL.
101+
This enables the same person details to be shown when the plunker is reloaded.
102+
103+
The `person` state definition:
104+
105+
```js
106+
const person = {
107+
name: 'person',
108+
url: '/people/:personId',
109+
component: Person,
110+
resolve: [{
111+
token: 'person',
112+
deps: ['$transition$'],
113+
resolveFn: (trans) => PeopleService.getPerson(trans.params().personId)
114+
}]
115+
}
116+
```
117+
118+
The URL will reflect the current `personId` parameter value, e.g., `/people/21`
119+
{: .notice--info}
120+
121+
The `person` resolve delegates to PeopleService to fetch the correct person.
122+
The resolveFn is injected with the `Transition` object because the first element of the `deps` property is the `$transition$` token.
123+
This way it can access the `personId` parameter.
124+
The `Transition` is a special injectable object with information about the current state transition.
125+
{: .notice--info}
126+
127+
### Linking with params
128+
129+
Note that our app's main Navigation Bar links to three states: `hello`, `about`, and `people`,
130+
but it doesn't include a link directly to the `person` state.
131+
This is because the state cannot be activated without a parameter value for the `personId` parameter.
132+
133+
In the `people` state we create links to the `person` state for each person.
134+
We still create the link using the `UISref` component, but we also include the `personId` parameter value.
135+
As we loop over each person object using `.map()`, we provide the `UISref` with the `personId` using each person's `.id` property.
136+
137+
{% raw %}
138+
```js
139+
let list = people.map((person, index) => (
140+
<li key={index}>
141+
<UISref to="person" params={{personId:person.id}}>
142+
<a>{person.name}</a>
143+
</UISref>
144+
</li>
145+
));
146+
```
147+
{% endraw %}
148+

0 commit comments

Comments
 (0)