Angular 2
ngrx
खोज…
परिचय
पूरा उदाहरण: एक उपयोगकर्ता लॉगिन / लॉगआउट करें
आवश्यक शर्तें
यह विषय Redux और / या Ngrx के बारे में नहीं है :
- आपको Redux के साथ सहज होने की आवश्यकता है
- कम से कम RxJs और ऑब्जर्वेबल पैटर्न की मूल बातें समझें
सबसे पहले, आइए एक उदाहरण को शुरू से ही परिभाषित करें और कुछ कोड के साथ खेलें:
एक डेवलपर के रूप में, मैं चाहता हूं:
- एक
IUser
इंटरफ़ेस है जोUser
के गुणों को परिभाषित करता है - उन क्रियाओं को घोषित करें जिनका उपयोग हम बाद में
User
कोStore
में हेरफेर करने के लिए करेंगे -
UserReducer
की प्रारंभिक स्थिति को परिभाषित करें - Reducer
UserReducer
बनाएँ -
Store
बनाने के लिए हमारेUserReducer
को हमारे मुख्य मॉड्यूल में आयात करें - हमारे विचार में जानकारी प्रदर्शित करने के लिए
Store
डेटा का उपयोग करें
स्पॉइलर अलर्ट : यदि आप डेमो को तुरंत आज़माना चाहते हैं या कोड शुरू करने से पहले, यहां तक कि हम यहां शुरू कर सकते हैं, एक प्लंकर ( व्यू या रन व्यू देखें )।
1) IUser
इंटरफ़ेस को परिभाषित करें
मुझे अपने इंटरफेस को दो भागों में विभाजित करना पसंद है:
- वे गुण जो हम सर्वर से प्राप्त करेंगे
- गुण जो हम केवल UI के लिए निर्धारित करते हैं (उदाहरण के लिए एक बटन कताई होना चाहिए)
और यहाँ IUser
का इंटरफ़ेस हम उपयोग करेंगे:
user.interface.ts
export interface IUser {
// from server
username: string;
email: string;
// for UI
isConnecting: boolean;
isConnected: boolean;
};
2) User
को हेरफेर करने के लिए कार्रवाई की घोषणा करें
अब हमें यह सोचने को मिला है कि हमारे रिड्यूसर को किस तरह की कार्रवाइयों को संभालना है।
यहाँ कहते हैं:
user.actions.ts
export const UserActions = {
// when the user clicks on login button, before we launch the HTTP request
// this will allow us to disable the login button during the request
USR_IS_CONNECTING: 'USR_IS_CONNECTING',
// this allows us to save the username and email of the user
// we assume those data were fetched in the previous request
USR_IS_CONNECTED: 'USR_IS_CONNECTED',
// same pattern for disconnecting the user
USR_IS_DISCONNECTING: 'USR_IS_DISCONNECTING',
USR_IS_DISCONNECTED: 'USR_IS_DISCONNECTED'
};
लेकिन इससे पहले कि हम उन कार्यों का उपयोग करें, मुझे समझाएं कि हमें उन कार्यों में से कुछ को भेजने के लिए एक सेवा की आवश्यकता क्यों है:
मान लीजिए कि हम एक उपयोगकर्ता को कनेक्ट करना चाहते हैं। तो हम एक लॉगिन बटन पर क्लिक करेंगे और यहाँ पर क्या होने वाला है:
- बटन पर क्लिक करें
- घटक ईवेंट को
userService.login
औरuserService.login
कॉलuserService.login
-
userService.login
विधिdispatch
एक घटना हमारे स्टोर संपत्ति अद्यतन करने के लिए:user.isConnecting
- एक HTTP कॉल निकाल दी जाती है (हम async व्यवहार का अनुकरण करने के लिए डेमो में
setTimeout
उपयोग करेंगे) - एक बार
HTTP
कॉल समाप्त होने के बाद, हम अपने स्टोर को चेतावनी देने के लिए एक और कार्रवाई भेजेंगे कि एक उपयोगकर्ता लॉग इन है
user.service.ts
@Injectable()
export class UserService {
constructor(public store$: Store<AppState>) { }
login(username: string) {
// first, dispatch an action saying that the user's tyring to connect
// so we can lock the button until the HTTP request finish
this.store$.dispatch({ type: UserActions.USR_IS_CONNECTING });
// simulate some delay like we would have with an HTTP request
// by using a timeout
setTimeout(() => {
// some email (or data) that you'd have get as HTTP response
let email = `${username}@email.com`;
this.store$.dispatch({ type: UserActions.USR_IS_CONNECTED, payload: { username, email } });
}, 2000);
}
logout() {
// first, dispatch an action saying that the user's tyring to connect
// so we can lock the button until the HTTP request finish
this.store$.dispatch({ type: UserActions.USR_IS_DISCONNECTING });
// simulate some delay like we would have with an HTTP request
// by using a timeout
setTimeout(() => {
this.store$.dispatch({ type: UserActions.USR_IS_DISCONNECTED });
}, 2000);
}
}
3) UserReducer
की प्रारंभिक स्थिति को परिभाषित करें
user.state.ts
export const UserFactory: IUser = () => {
return {
// from server
username: null,
email: null,
// for UI
isConnecting: false,
isConnected: false,
isDisconnecting: false
};
};
4) Reducer UserReducer
बनाएँ
एक Reducer 2 तर्क लेता है:
- वर्तमान राज्य
- टाइप
Action
का एकAction
Action<{type: string, payload: any}>
अनुस्मारक: कुछ बिंदु पर एक reducer को आरंभ करने की आवश्यकता है
जैसा कि हमने भाग 3 में अपने रिड्यूसर की डिफ़ॉल्ट स्थिति को परिभाषित किया है), हम इसका उपयोग करने में सक्षम होंगे:
user.reducer.ts
export const UserReducer: ActionReducer<IUser> = (user: IUser, action: Action) => {
if (user === null) {
return userFactory();
}
// ...
}
उम्मीद है, यह लिखने का एक आसान तरीका है कि किसी वस्तु को वापस करने के लिए हमारे factory
फ़ंक्शन का उपयोग करके और reducer के भीतर एक (ES6) डिफ़ॉल्ट पैरामीटर मान का उपयोग करें :
export const UserReducer: ActionReducer<IUser> = (user: IUser = UserFactory(), action: Action) => {
// ...
}
फिर, हमें अपने reducer में हर क्रिया को संभालने की आवश्यकता है: TIP : हमारे राज्य को अपरिवर्तनीय रखने के लिए ES6 Object.assign
फ़ंक्शन का उपयोग करें
export const UserReducer: ActionReducer<IUser> = (user: IUser = UserFactory(), action: Action) => {
switch (action.type) {
case UserActions.USR_IS_CONNECTING:
return Object.assign({}, user, { isConnecting: true });
case UserActions.USR_IS_CONNECTED:
return Object.assign({}, user, { isConnecting: false, isConnected: true, username: action.payload.username });
case UserActions.USR_IS_DISCONNECTING:
return Object.assign({}, user, { isDisconnecting: true });
case UserActions.USR_IS_DISCONNECTED:
return Object.assign({}, user, { isDisconnecting: false, isConnected: false });
default:
return user;
}
};
5) Store
बनाने के लिए हमारे UserReducer
को हमारे मुख्य मॉड्यूल में आयात करें
app.module.ts
@NgModule({
declarations: [
AppComponent
],
imports: [
// angular modules
// ...
// declare your store by providing your reducers
// (every reducer should return a default state)
StoreModule.provideStore({
user: UserReducer,
// of course, you can put as many reducers here as you want
// ...
}),
// other modules to import
// ...
]
});
6) हमारे विचार में जानकारी प्रदर्शित करने के लिए Store
डेटा का उपयोग करें
सब कुछ अब तर्क की तरफ से तैयार है और हमें बस यह प्रदर्शित करना है कि हम दो घटकों में क्या चाहते हैं:
-
UserComponent
: [डंब कंपोनेंट] हम@Input
प्रॉपर्टी औरasync
पाइप का उपयोग करके यूजर ऑब्जेक्ट को स्टोर से पास करेंगे। इस तरह, घटक केवल उपलब्ध होने परuser
कोuser
करेगा (औरuser
प्रकारIUser
और प्रकार का नहींObservable<IUser>
!) -
LoginComponent
[स्मार्ट घटक] हम सीधेStore
को इस घटक में इंजेक्ट करेंगे और केवल एकObservable
रूप मेंuser
पर काम करेंगे।
user.component.ts
@Component({
selector: 'user',
styles: [
'.table { max-width: 250px; }',
'.truthy { color: green; font-weight: bold; }',
'.falsy { color: red; }'
],
template: `
<h2>User information :</h2>
<table class="table">
<tr>
<th>Property</th>
<th>Value</th>
</tr>
<tr>
<td>username</td>
<td [class.truthy]="user.username" [class.falsy]="!user.username">
{{ user.username ? user.username : 'null' }}
</td>
</tr>
<tr>
<td>email</td>
<td [class.truthy]="user.email" [class.falsy]="!user.email">
{{ user.email ? user.email : 'null' }}
</td>
</tr>
<tr>
<td>isConnecting</td>
<td [class.truthy]="user.isConnecting" [class.falsy]="!user.isConnecting">
{{ user.isConnecting }}
</td>
</tr>
<tr>
<td>isConnected</td>
<td [class.truthy]="user.isConnected" [class.falsy]="!user.isConnected">
{{ user.isConnected }}
</td>
</tr>
<tr>
<td>isDisconnecting</td>
<td [class.truthy]="user.isDisconnecting" [class.falsy]="!user.isDisconnecting">
{{ user.isDisconnecting }}
</td>
</tr>
</table>
`
})
export class UserComponent {
@Input() user;
constructor() { }
}
login.component.ts
@Component({
selector: 'login',
template: `
<form
*ngIf="!(user | async).isConnected"
#loginForm="ngForm"
(ngSubmit)="login(loginForm.value.username)"
>
<input
type="text"
name="username"
placeholder="Username"
[disabled]="(user | async).isConnecting"
ngModel
>
<button
type="submit"
[disabled]="(user | async).isConnecting || (user | async).isConnected"
>Log me in</button>
</form>
<button
*ngIf="(user | async).isConnected"
(click)="logout()"
[disabled]="(user | async).isDisconnecting"
>Log me out</button>
`
})
export class LoginComponent {
public user: Observable<IUser>;
constructor(public store$: Store<AppState>, private userService: UserService) {
this.user = store$.select('user');
}
login(username: string) {
this.userService.login(username);
}
logout() {
this.userService.logout();
}
}
चूंकि Ngrx
Redux
और RxJs
अवधारणाओं का एक मर्ज है, इसलिए Ngrx
में Ngrx
को एक RxJs
समझना काफी कठिन हो सकता है। लेकिन यह एक शक्तिशाली पैटर्न है जो आपको अनुमति देता है जैसा कि हमने इस उदाहरण में देखा है कि एक प्रतिक्रियाशील ऐप है और क्या आप आसानी से अपना डेटा साझा कर सकते हैं। यह मत भूलो कि वहाँ एक प्लंकर उपलब्ध है और आप इसे अपने खुद के परीक्षण बनाने के लिए कांटा कर सकते हैं!
मुझे आशा है कि यह मददगार था यहां तक कि विषय काफी लंबा है, चीयर्स!