Skip to content

Commit a6c4aaf

Browse files
dragersmithad15
authored andcommitted
feat: Introduced a new function called provideStore() which accepts a already created Redux store (angular-redux#142)
* feat: Introduced a new function called provideStore() which accepts a already created Redux store This function accepts a already created Redux store so the users can themselves create a store exactly how they want to do it. The configureStore() function can also be used just like before. * doc: Fix where constant variable is reassigned (angular-redux#141) * doc: Fix where constant variable is reassigned * fix: Update to import syntax in docs * doc: Fix typos * doc: Fix typos in changelog * doc: Fix typos in readme * doc: Fix typo in readme
1 parent da98ee3 commit a6c4aaf

File tree

4 files changed

+242
-36
lines changed

4 files changed

+242
-36
lines changed

packages/store/CHANGELOG.md

+66-6
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,63 @@
1+
# 3.2.0
2+
3+
### Features
4+
5+
* Added a `provideStore()` function which lets you pass in a already created
6+
store. It can be used as this:
7+
8+
Create your store:
9+
```typescript
10+
// store.ts
11+
12+
import {
13+
applyMiddleware,
14+
Store,
15+
combineReducers,
16+
compose,
17+
createStore
18+
} from 'redux';
19+
import thunk from 'redux-thunk';
20+
import reduxLogger from 'redux-logger';
21+
22+
import { myReducer } from './reducers/my-reducer';
23+
24+
const rootReducer = combineReducers({
25+
myReducer,
26+
});
27+
28+
export const store = createStore(
29+
rootReducer,
30+
compose(
31+
applyMiddleware(
32+
thunk,
33+
reduxLogger
34+
)
35+
)
36+
) as Store
37+
```
38+
39+
Create your App and call `provideStore` with your newly created store:
40+
```typescript
41+
// app.ts
42+
43+
import { NgRedux } from 'ng2-redux';
44+
import { store } from './store.ts';
45+
46+
interface IAppState {
47+
// ...
48+
};
49+
@Component({
50+
// ... etc.
51+
})
52+
class App {
53+
constructor(private ngRedux: NgRedux) {
54+
this.ngRedux.provideStore(store);
55+
}
56+
57+
// ...
58+
}
59+
```
60+
161
# 3.1.0
262

363
### Features
@@ -11,7 +71,7 @@ an observable.
1171
```js
1272
import { is } from 'immutablejs'
1373

14-
export class SomeComponent {
74+
export class SomeComponent {
1575
@select(n=n.some.selector, is) someSelector$: Observable<any>
1676
}
1777

@@ -29,7 +89,7 @@ export class SomeComponent {
2989
### Features
3090

3191
#### Select Decorator
32-
This release introduces the new decorator interface. You can now use
92+
This release introduces the new decorator interface. You can now use
3393
`@select` to create an observable from a slice of store state.
3494

3595
See 'the select pattern' in [README.md](README.md#the-select-pattern)
@@ -132,17 +192,17 @@ community: `redux-logger` and `redux-localstorage`.
132192

133193
### Features
134194

135-
* **Type definitions**:
195+
* **Type definitions**:
136196
* Ported to typescript
137-
* Supports typed stores / reducers
197+
* Supports typed stores / reducers
138198
* Uses offical Redux type definitions
139199
* **Type Injectable**:
140200
* Able to inject `NgRedux` into your component by type, and not need `@Inject('ngRedux')`
141201
* `@Inject('ngRedux')` still works
142202

143203
```typescript
144204
import { NgRedux } from 'ng2-redux';
145-
// ...
205+
// ...
146206
export class MyComponent {
147207
constructor(private ngRedux: NgRedux) {}
148208
}
@@ -181,7 +241,7 @@ export class MyComponent implements OnInit {
181241
person$: Observable<Map<string,any>>;
182242

183243
constructor(private ngRedux: ngRedux) {
184-
// even if the reference of the object has changed,
244+
// even if the reference of the object has changed,
185245
// if the data is the same - it wont be treated as a change
186246
this.person$ = this.ngRedux.select(state=>state.people.get(0),is);
187247
}

packages/store/README.md

+98-8
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,62 @@ class App {
7070
}
7171
```
7272

73+
Or if you prefer to create the Redux store yourself you can do that and use the
74+
`provideStore()` function instead.
75+
76+
Create your store:
77+
```typescript
78+
// store.ts
79+
80+
import {
81+
applyMiddleware,
82+
Store,
83+
combineReducers,
84+
compose,
85+
createStore
86+
} from 'redux';
87+
import thunk from 'redux-thunk';
88+
import reduxLogger from 'redux-logger';
89+
90+
import { myReducer } from './reducers/my-reducer';
91+
92+
const rootReducer = combineReducers({
93+
myReducer,
94+
});
95+
96+
export const store = createStore(
97+
rootReducer,
98+
compose(
99+
applyMiddleware(
100+
thunk,
101+
reduxLogger
102+
)
103+
)
104+
) as Store
105+
```
106+
107+
Create your App and call `provideStore` with your newly created store:
108+
```typescript
109+
// app.ts
110+
111+
import { NgRedux } from 'ng2-redux';
112+
import { store } from './store.ts';
113+
114+
interface IAppState {
115+
// ...
116+
};
117+
@Component({
118+
// ... etc.
119+
})
120+
class App {
121+
constructor(private ngRedux: NgRedux) {
122+
this.ngRedux.provideStore(store);
123+
}
124+
125+
// ...
126+
}
127+
```
128+
73129
Now your Angular 2 app has been reduxified!
74130

75131
## Usage
@@ -85,19 +141,19 @@ preferred approach to accessing store data in Angular 2.
85141

86142
#### The @select decorator
87143

88-
The `@select` decorator can be added to the property of any class or angular
144+
The `@select` decorator can be added to the property of any class or angular
89145
component/injectable. It will turn the property into an observable which observes
90146
the Redux Store value which is selected by the decorator's parameter.
91147

92148
The decorator expects to receive a `string`, an array of `string`s, a `function` or no
93-
parameter at all.
149+
parameter at all.
94150

95151
- If a `string` is passed the `@select` decorator will attempt to observe a store
96152
property whose name matches the `string`.
97153
- If an array of strings is passed, the decorator will attempt to match that path
98154
through the store (similar to `immutableJS`'s `getIn`).
99155
- If a `function` is passed the `@select` decorator will attempt to use that function
100-
as a selector on the RxJs observable.
156+
as a selector on the RxJs observable.
101157
- If nothing is passed then the `@select` decorator will attempt to use the name of the class property to find a matching value in the Redux store. Note that a utility is in place here where any $ characters will be ignored from the class property's name.
102158

103159
```typescript
@@ -137,7 +193,7 @@ export class CounterValue {
137193
@select(state => state.counter) counterSelectedWithFunction;
138194

139195
// this selects `counter` from the store and multiples it by two
140-
@select(state => state.counter * 2)
196+
@select(state => state.counter * 2)
141197
counterSelectedWithFuntionAndMultipliedByTwo: Observable<any>;
142198
}
143199
```
@@ -448,7 +504,7 @@ class App {
448504

449505
### `configureStore()`
450506

451-
Initializes your ngRedux store. This should be called once, typically in your
507+
Adds your ngRedux store to NgRedux. This should be called once, typically in your
452508
top-level app component's constructor.
453509

454510
__Arguments:__
@@ -467,13 +523,47 @@ Async pipe to bind its values into your template.
467523

468524
__Arguments:__
469525

470-
* `key` \(*string*): A key within the state that you want to subscribe to.
471-
* `selector` \(*Function*): A function that accepts the application state, and returns the slice you want subscribe to for changes.
526+
* `key` \(*string*): A key within the state that you want to subscribe to.
527+
* `selector` \(*Function*): A function that accepts the application state, and returns the slice you want subscribe to for changes.
528+
529+
e.g:
530+
```typescript
531+
this.counter$ = this.ngRedux.select(state=>state.counter);
532+
// or
533+
this.counterSubscription = this.ngRedux
534+
.select(state=>state.counter)
535+
.subscribe(count=>this.counter = count);
536+
// or
537+
538+
this.counter$ = this.ngRedux.select('counter');
539+
```
540+
541+
### `provideStore()`
542+
543+
Initializes your ngRedux store. This should be called once, typically in your
544+
top-level app component's constructor. If `configureStore`
545+
has been used this cannot be used.
546+
547+
__Arguments:__
548+
549+
* `store` \(*Store*): Your app's store.
550+
551+
### select(key | function,[comparer]) => Observable
552+
553+
Exposes a slice of state as an observable. Accepts either a property name or a selector function.
554+
555+
If using the async pipe, you do not need to subscribe to it explicitly, but can use the angular
556+
Async pipe to bind its values into your template.
557+
558+
__Arguments:__
559+
560+
* `key` \(*string*): A key within the state that you want to subscribe to.
561+
* `selector` \(*Function*): A function that accepts the application state, and returns the slice you want subscribe to for changes.
472562

473563
e.g:
474564
```typescript
475565
this.counter$ = this.ngRedux.select(state=>state.counter);
476-
// or
566+
// or
477567
this.counterSubscription = this.ngRedux
478568
.select(state=>state.counter)
479569
.subscribe(count=>this.counter = count);

packages/store/src/___tests___/components/ng-redux.spec.ts

+32-1
Original file line numberDiff line numberDiff line change
@@ -125,11 +125,12 @@ describe('NgRedux Observable Store', () => {
125125
bar: string;
126126
baz: number;
127127
};
128-
128+
129129
let connector;
130130
let targetObj;
131131
let defaultState;
132132
let rootReducer;
133+
let store;
133134
let ngRedux;
134135
let mockAppRef;
135136

@@ -153,6 +154,7 @@ describe('NgRedux Observable Store', () => {
153154
}
154155
};
155156

157+
store = createStore(rootReducer);
156158
ngRedux = new NgRedux<IAppState>();
157159
ngRedux.configureStore(rootReducer, defaultState);
158160
});
@@ -272,4 +274,33 @@ describe('NgRedux Observable Store', () => {
272274
expect(fooData.data).to.equal('update-2');
273275
expect(spy).to.have.been.calledThrice;
274276
});
277+
278+
it('should throw when the store is provided after it has been configured',
279+
() => {
280+
// Configured once in beforeEach, now we try to provide a store when
281+
// we already have configured one.
282+
283+
expect(ngRedux.provideStore.bind(store))
284+
.to.throw(Error);
285+
});
286+
287+
it('should set the store when a store is provided',
288+
() => {
289+
290+
delete ngRedux._store;
291+
delete ngRedux._$store;
292+
293+
expect(ngRedux._store).to.be.undefined;
294+
expect(ngRedux._$store).to.be.undefined;
295+
296+
expect(ngRedux.provideStore.bind(ngRedux, store))
297+
.to.not.throw(Error);
298+
299+
expect(ngRedux._store).to.have.all.keys(
300+
'dispatch',
301+
'subscribe',
302+
'getState',
303+
'replaceReducer'
304+
);
305+
});
275306
});

0 commit comments

Comments
 (0)