2017-02-21 25 views
8

पर नेविगेट करें मैं ngrx और Redux शैली आर्किटेक्चर के लिए नया हूं और मुझे समस्याएं आ रही हैं कि मुझे कार्रवाई क्रियाओं को कैसे प्रभावित करना चाहिए। एक उदाहरण बुनियादी कार्यक्षमता प्राप्त कर रहा है जैसे उपयोगकर्ता लॉग इन करने के बाद कोई कार्रवाई करना। मेरा मुख्य संघर्ष यह है कि उपयोगकर्ता लॉग इन करने के बाद की जाने वाली कार्रवाई को आवेदन की वर्तमान स्थिति के आधार पर अलग-अलग किया जाएगा - उपयोगकर्ता कहीं भी हो सकता है लॉगिन प्रॉम्प्ट/पेज के साथ प्रस्तुत किए जाने पर एप्लिकेशन में।ngrx चेनिंग क्रिया/प्रभाव - उदाहरण के लिए लॉगिन करें और फिर

कोई भी उदाहरण मैंने हार्डकोड प्रभाव देखा है जो उपयोगकर्ता द्वारा लॉग इन करने के बाद होगा। मेरे परिदृश्य में यह ऊपर बताए अनुसार ठीक से फिट नहीं होता है, मैं हमेशा एक ही कार्रवाई नहीं करना चाहता हूं।

यहां होम पेज का कुछ उदाहरण कोड है जिसमें लॉगिन घटक शामिल है। इस परिदृश्य में मैं उपयोगकर्ता/खरीदें 'पर पुनः निर्देशित किया करने के लिए एक बार वे में प्रवेश करने वाले चाहते हैं

@Component(..) 
export class HomePageComponent { 
    constructor(private store: Store<any>) { 
    } 

    public onLoginSubmitted(username, password) { 
     this.store.dispatch(new loginActions.Login({username, password})); 
     // once this has happened successfully navigate to /buy  
    } 

} 

उदाहरण प्रभाव

@Injectable() 
export class LoginEffects { 

    ......  

    @Effect() 
    login$ = this.actions$ 
     .ofType(loginActions.ActionTypes.LOGIN) 
     .switchMap((data) => { 
      return this.loginService.login(data.payload) 
       .map(() => new loginActions.LoginSuccess({loggedIn: true, isLoggingIn: false})) 
       .catch((error) => { 
        return of(new loginActions.LoginError({loggedIn: false, isLoggingIn: false})); 
       }); 
     }); 
    ...... 
} 

मैं कैसे आप इस समस्या को हल कर सकते हैं पर कई विचार किया है। - लेकिन उनमें से कोई भी सही महसूस नहीं करता है। ये

  • लॉगिन पेलोड के साथ डेटा गुजर एक कार्रवाई निर्धारित करने के लिए अगले
  • प्रभाव जो LoginSuccess पर कार्रवाई करने, लेकिन कुछ उच्च स्तर
  • पर फ़िल्टर्ड रहे हैं सुनकर एक घटक विशेष प्रभाव लिखने के बहुत सारे लेखन लेने के लिए शामिल स्टोर पर घटनाओं के लिए (क्या यह संभव/खराब अभ्यास है?)
  • वर्तमान लॉगिन स्थिति के बारे में स्टोर से डेटा पढ़ने और घटक में इस पर कार्य करने के लिए। हालांकि यह तर्क तुरंत चलाया जाएगा, जिसके पास वांछित प्रभाव नहीं हो सकता है

क्या कोई मुझे सही पथ/वर्तमान उदाहरणों को इंगित कर सकता है कि इसे हल किया जाना चाहिए?

+0

पेलोड का हिस्सा 'रीडायरेक्ट रूट' हो सकता है, और फिर लॉगिन के बाद, 'LoginSuccess' प्रभाव' रीडायरेक्ट रूट 'निर्दिष्ट करता है, इस पर आधारित नेविगेट करेगा। आपके पास केवल एक 'loginSuccess' कार्रवाई होगी, लेकिन यह कहीं भी रीडायरेक्ट कर सकती है। – Adam

+0

यह हो सकता है - लेकिन यह मानता है कि आप हमेशा लॉगिन के बाद रीडायरेक्ट करना चाहते हैं। यह आवश्यक रूप से मामला नहीं हो सकता है, उदाहरण के लिए आप एक मॉडल – dannym

उत्तर

9

एक प्रभाव क्रियाओं की एक श्रृंखला पर mergeMap का उपयोग करके कई क्रियाओं को बंद कर सकता है। मैं आमतौर पर क्या करता हूं, अतिरिक्त कार्यों में गुजरता हूं जिन्हें मैं लॉगिन प्रभाव को प्रेषित करना चाहता हूं।

@Component(..) 
export class HomePageComponent { 
    constructor(private store: Store<any>) { } 

    public onLoginSubmitted(username, password) { 
     this.store.dispatch(new loginActions.Login({ 
      username, 
      password, 
      onCompleteActions: [new loginActions.Redirect({ route: '/buy' })] })); 
    } 
} 

लॉगिन प्रभाव तो प्रेषण किसी भी पारित कर दिया-इन mergeMap का उपयोग कर कार्रवाई। आपको अभी भी प्रत्येक क्रिया के लिए प्रभाव बनाना होगा, लेकिन अब आप रीडायरेक्ट एक्शन जैसे अधिक पुन: प्रयोज्य क्रियाएं बना सकते हैं।

@Injectable() 
export class LoginEffects { 

    ......  

    @Effect() 
    login$ = this.actions$ 
     .ofType(loginActions.ActionTypes.LOGIN) 
     .switchMap((data) => { 
      let mappedActions = [new loginActions.LoginSuccess({loggedIn: true, isLoggingIn: false})]; 
      if (data.payload.onCompleteActions) 
       mappedActions = mappedActions.concat(data.payload.onCompleteActions); 

      return this.loginService.login(data.payload) 
       .mergeMap(mappedActions) 
       .catch((error) => { 
        return of(new loginActions.LoginError({loggedIn: false, isLoggingIn: false})); 
       }); 
     }); 

    ...... 
} 

मैं इस समाधान के बारे में क्या पसंद है कि यह भविष्य में स्केलेबल है, क्योंकि किसी भी कार्रवाई में पारित किया जा सकता है, और कोई स्विच है या अगर-किसी और पेड़ क्या करना है तय करने के लिए। आप कई कार्रवाइयों में भी गुजर सकते हैं, इसलिए 'redirectAndAndoseModal' एक्शन बनाने की कोई आवश्यकता नहीं है, आप redirect के साथ-साथ closeModal में पास कर सकते हैं। आप टिप्पणी के बारे में, यह सिर्फ मार्ग परिवर्तन आप लॉगिन बंद करना चाहते हैं हो सकता है कि नहीं है कुछ भी इस तरह के समापन के रूप में, यह हो सकता है,:

this.store.dispatch(new loginActions.Login({ 
    username, 
    password, 
    onCompleteActions: [new loginActions.Redirect({ route: '/buy' }), new modalActions.CloseModal()] })); 

आप थोड़ा अधिक dispatching multiple Actions from one @Effect() at this github issue. के बारे में

संपादित पढ़ सकते हैं एक मॉडल, और इसके लिए देखने के लिए कोई सामान्य तरीका नहीं है।आप runLoginActions बूलियन जैसे स्टोर में कुछ जोड़ सकते हैं, और फिर लॉगिन अनुरोध के बाद आपके स्टोर से उस डेटा को पढ़ लें।

फिर अपने login$ प्रभाव में, आप स्टोर से अतिरिक्त क्रियाओं को चलाने का निर्णय लेने के लिए पढ़ सकते हैं या नहीं।

@Effect() 
login$: Observable<Action> = this.actions$ 
    .ofType(auth.actionTypes.LOGIN) 
    .map((action: auth.LoginAction) => action.payload) 
    .switchMap((user) => { 
     let successAction = new loginActions.LoginSuccess({loggedIn: true, isLoggingIn: false}); 
     let mappedActions = [successAction]; 
     if (data.payload.onCompleteAction) 
      mappedActions.push(data.payload.onCompleteAction); 

     return this.authService.login(user.username, user.password) 
      .withLatestFrom(this.store) 
      .mergeMap(([result, store]) => store.runLoginActions ? 
       [mappedActions] : 
       [successAction] 
      ) 
      .catch((err) => { 
       try { 
        return of(new auth.NetworkFailureAction(err[0].code)); 
       } catch (e) { 
        throw `Array not in the expected format of [{ code: "", message: "" }]`; 
       } 
      }); 
    }); 

ध्यान दें कि loginSuccess के लिए अपने कम करने में, आप अपने runLoginActions = true स्थापित करना चाहिए, और यह डिफ़ॉल्ट रूप से के रूप में सही शुरू कर देना चाहिए, केवल बंद कर दिया करने के लिए किया जा जब एक मार्ग बदल दिया गया है, या एक घटक नष्ट हो जाता है।

ध्यान रखें कि यह एक सामान्य समाधान है, और यदि आप अपने reducers अद्यतन करते हैं, कार्रवाई अपने आप को जोड़ने की जरूरत है के लिए जा रहे आदि

यह एक मैनुअल प्रक्रिया का एक और अधिक है, लेकिन नहीं करने के लिए अपने मामलों के बाद से कार्य करने की इच्छा बहुत विशिष्ट हैं, यह संभवतः इस तरह से किया जाना चाहिए।

+0

को बर्खास्त करना चाहते हैं मुझे यह समाधान पसंद है। मेरे पास एक सवाल यह है कि क्या इन कार्यों को रद्द कर दिया जा सकता है? जैसे उपयोगकर्ता लॉग इन करने के लिए और कहीं और नेविगेट करने के लिए इंतजार कर रहा था, हम रीडायरेक्ट को रद्द करना चाहते हैं जो लॉगिन कॉल के बाद होता है – dannym

+0

क्या आप लॉगिन रद्द करना चाहते हैं? सर्वर को अभी भी बताया जाएगा कि उपयोगकर्ता ने लॉग इन किया है, लेकिन अब कोणीय क्लाइंट ने प्रतिक्रिया को अनदेखा कर दिया है और सर्वर के साथ समन्वयित नहीं है। किसी भी तरह से, मैं इसमें देख रहा हूं क्योंकि मुझे – Adam

+0

का उत्तर नहीं है, आप लॉगिन रद्द नहीं करना चाहते हैं, लेकिन आप बाद में रीडायरेक्ट को रद्द करना चाहते हैं। यहां एक स्थिति है - उपयोगकर्ता होम पेज पर जाता है। होम पेज पर एक लॉगिन फॉर्म और एक एफएक्यू बटन है। उपयोगकर्ता विवरण और क्लिक लॉगिन में डालता है। हालांकि अनुरोध प्रसंस्करण हो रहा है, वे ऊब जाते हैं और अक्सर पूछे जाने वाले प्रश्न बटन पर क्लिक करते हैं और अक्सर पूछे जाने वाले प्रश्न पृष्ठ पर जाते हैं और अक्सर पूछे जाने वाले प्रश्न पूछते हैं। एक बार आपका लॉगिन अनुरोध लौटाए जाने के बाद अब आप उपयोगकर्ता को रीडायरेक्ट नहीं करना चाहते हैं। – dannym

संबंधित मुद्दे