2016-02-27 8 views
6

मेरा प्रश्न: मेरे अपरिवर्तनीय स्थिति (मानचित्र) में किसी सरणी में किसी ऑब्जेक्ट की संपत्ति को अपडेट क्यों नहीं किया जा रहा है, जिससे रेडक्स मेरे घटक को अपडेट नहीं कर सकता है?रेडक्स घटकों को अद्यतन नहीं कर रहा है जब गहरे अपरिवर्तनीय राज्य गुण अपडेट किए जाते हैं

मैं (मेरे UploaderReducer अंदर से आप नीचे देख होगा) वस्तु इस तरह दिखता है एक विजेट है कि मेरे सर्वर पर फ़ाइलें अपलोड करता है, और मेरी प्रारंभिक अवस्था बनाने के लिए कोशिश कर रहा हूँ:

let initState = Map({ 
    files: List(), 
    displayMode: 'grid', 
    currentRequests: List() 
}); 

मैं एक thunk है एक घटना होती है जब एक घटना होती है (जैसे एक प्रगति अद्यतन) अपलोड करता है और क्रियाओं को प्रेषित करता है। उदाहरण के लिए, onProgress घटना इस तरह दिखता है:

export default UploaderReducer = handleActions({ 
    // Other actions... 
    FILE_UPLOAD_PROGRESS_UPDATED: (state, { payload }) => (
    updateFilePropsAtIndex(
     state, 
     payload.index, 
     { 
     status: FILE_UPLOAD_PROGRESS_UPDATED, 
     progress: payload.progress 
     } 
    ) 
) 
    }, initState); 

और updateFilePropsAtIndex की तरह दिखता है:

onProgress: (data) => { 
    dispatch(fileUploadProgressUpdated({ 
     index, 
     progress: data.percentage 
    })); 
    } 

मैं बना सकते हैं और अपने कार्यों को संभालने के लिए redux-actions उपयोग कर रहा हूँ, ताकि कार्रवाई के लिए मेरी कम करने इस तरह दिखता है :

export function updateFilePropsAtIndex (state, index, fileProps) { 
    return state.updateIn(['files', index], file => { 
    try { 
     for (let prop in fileProps) { 
     if (fileProps.hasOwnProperty(prop)) { 
      if (Map.isMap(file)) { 
      file = file.set(prop, fileProps[prop]); 
      } else { 
      file[prop] = fileProps[prop]; 
      } 
     } 
     } 
    } catch (e) { 
     console.error(e); 
     return file; 
    } 

    return file; 
    }); 
} 

अब तक, यह सब लगता ठीक से काम करने के लिए! Redux DevTools में, यह अपेक्षित कार्रवाई के रूप में दिखाई देता है। हालांकि, मेरे घटकों में से कोई भी अपडेट नहीं है! files सरणी के लिए नए आइटम जोड़ना फिर से renders नई फ़ाइलें के साथ मेरी यूआई, जोड़ा तो Redux निश्चित रूप से एक समस्या नहीं है मुझे ऐसा करने के साथ ...

मेरे शीर्ष स्तर घटक connect दिखता का उपयोग कर दुकान से कनेक्ट होता है इस तरह:

const mapStateToProps = function (state) { 
    let uploadReducer = state.get('UploaderReducer'); 
    let props = { 
    files: uploadReducer.get('files'), 
    displayMode: uploadReducer.get('displayMode'), 
    uploadsInProgress: uploadReducer.get('currentRequests').size > 0 
    }; 

    return props; 
}; 

class UploaderContainer extends Component { 
    constructor (props, context) { 
    super(props, context); 
    // Constructor things! 
    } 

    // Some events n stuff... 

    render(){ 
     return (
     <div> 
     <UploadWidget 
      //other props 
      files={this.props.files} /> 
     </div> 
     ); 
    } 
} 

export default connect(mapStateToProps, uploadActions)(UploaderContainer); 

uploadActionsredux-actions उपयोग कर बनाई गई कार्रवाई के साथ एक वस्तु है।

files सरणी में एक file वस्तु मूल रूप से यह है:

{ 
    name: '', 
    progress: 0, 
    status 
} 

UploadWidget मूल रूप से एक खींचें n ड्रॉप div और एक files सरणी स्क्रीन पर मुद्रित है।

मैं redux-immutablejs का उपयोग कर मदद करने के लिए के रूप में मैं GitHub पर कई पदों में देखा है की कोशिश की, लेकिन मैं अगर यह मदद करता है पता नहीं है ... यह मेरा जड़ कम करने है:

import { combineReducers } from 'redux-immutablejs'; 
import { routeReducer as router } from 'redux-simple-router'; 
import UploaderReducer from './modules/UploaderReducer'; 

export default combineReducers({ 
    UploaderReducer, 
    router 
}); 

मेरा ऐप प्रवेश बिंदु इस तरह दिखता है:

const store = configureStore(Map({})); 

syncReduxAndRouter(history, store, (state) => { 
    return state.get('router'); 
}); 

// Render the React application to the DOM 
ReactDOM.render(
    <Root history={history} routes={routes} store={store}/>, 
    document.getElementById('root') 
); 

अन्त में, मेरी <Root/> घटक इस तरह दिखता है:

import React, { PropTypes } from 'react'; 
import { Provider } from 'react-redux'; 
import { Router } from 'react-router'; 

export default class Root extends React.Component { 
    static propTypes = { 
    history: PropTypes.object.isRequired, 
    routes: PropTypes.element.isRequired, 
    store: PropTypes.object.isRequired 
    }; 

    get content() { 
    return (
     <Router history={this.props.history}> 
     {this.props.routes} 
     </Router> 
    ); 
    } 

//Prep devTools, etc... 

    render() { 
    return (
     <Provider store={this.props.store}> 
     <div style={{ height: '100%' }}> 
      {this.content} 
      {this.devTools} 
     </div> 
     </Provider> 
    ); 
    } 
} 

तो, अंत में, अगर मैं निम्नलिखित राज्य वस्तु में एक 'प्रगति' अद्यतन करने के लिए प्रयास करते हैं,/Redux मेरी घटकों को अपडेट नहीं करता प्रतिक्रिया:

{ 
    UploaderReducer: { 
     files: [{progress: 0}] 
    } 
} 

ऐसा क्यों है? मैंने सोचा कि Immutable.js का उपयोग करने का पूरा विचार यह था कि संशोधित वस्तुओं की तुलना करना आसान था, भले ही आप उन्हें कितनी गहराई से अपडेट करते हैं? How to use Immutable.js with redux? https://github.com/reactjs/redux/issues/548

हालांकि, अपरिवर्तनीय का उपयोग कर के बताया लाभ इस लड़ाई के लायक होने लगते हैं और मैं आंकड़ा करने में खुशी होगी:

यह आम तौर पर Redux के साथ काम करने अपरिवर्तनीय हो रही लगता है के रूप में यह लगता है के रूप में सरल नहीं है क्या मैं गलत कर रहा हूँ!

अद्यतन अप्रैल 10 वर्ष 2016 चयनित जवाब ने मुझे बताया मैं गलत और पूर्णता के लिए के लिए क्या कर रहा था, मेरे updateFilePropsAtIndex समारोह अब शामिल बस इस:

return state.updateIn(['files', index], file => 
    Object.assign({}, file, fileProps) 
); 

यह पूरी तरह से अच्छी तरह से काम करता है! :) पहले

+0

जब आप कहते हैं कि "घटक नहीं किया जा रहा है अपडेट किया गया "क्या आपका मतलब है कि इसे रेडक्स से नए प्रोप नहीं मिल रहे हैं? क्या MapStateToProps को अद्यतन प्रगति प्राप्त नहीं होती है?Reducer के बारे में, क्या कार्रवाई पेलोड में सही प्रगति है? – azium

+0

अपलोडरकंटनर mapStateToProps फ़ंक्शन बिलकुल नहीं है, राज्यों को अपेक्षित मूल्यों के साथ DevTools में अपडेट किए जाने के बावजूद। मेरे पास यूनिट परीक्षणों की जांच है कि मैं जो कर रहा हूं वह काम करना चाहिए, इसलिए मुझे ऐसा लगता है कि रेडक्स स्तर पर मुझे कुछ समझ नहीं आ रहा है, लेकिन मुझे नहीं पता कि यह क्या है! –

+0

क्या आप जेएसबीन पर ऑनलाइन काम कर रहे उदाहरण प्राप्त कर सकते हैं? यह काम करना आसान हो गया है। – whitep4nther

उत्तर

5

दो सामान्य विचार:

  • Immutable.js, संभावित उपयोगी है हाँ, लेकिन आप इसे का उपयोग किए बिना डेटा के एक ही अपरिवर्तनीय हैंडलिंग पूरा कर सकते हैं। वहां कई पुस्तकालय हैं जो अपरिवर्तनीय डेटा अपडेट को पढ़ने में आसान बनाने में मदद कर सकते हैं, लेकिन फिर भी सादे वस्तुओं और सरणी पर काम करते हैं। मेरे पास उनमें से कई ने मेरे Redux- संबंधित पुस्तकालय रेपो में Immutable Data पृष्ठ पर सूचीबद्ध किया है।
  • यदि कोई प्रतिक्रिया घटक अद्यतन नहीं होता प्रतीत होता है, तो यह लगभग हमेशा होता है क्योंकि एक reducer वास्तव में डेटा को म्यूट कर रहा है। रेडक्स एफएक्यू के पास उस विषय पर http://redux.js.org/docs/FAQ.html#react-not-rerendering पर एक उत्तर है।

अब, यह देखते हुए कि आप हैं Immutable.js का उपयोग कर, मैं डेटा की है कि उत्परिवर्तन स्वीकार करेंगे थोड़ा संभावना नहीं लगता है। उस ने कहा ... आपके reducer में file[prop] = fileProps[prop] लाइन बहुत उत्सुक लगती है। आप वहां पर क्या होने की उम्मीद कर रहे हैं? मैं उस हिस्से पर एक अच्छा नज़र डालेगा।

दरअसल, अब मैं इसे देखता हूं ... मैं लगभग 100% निश्चित हूं कि आप डेटा को म्यूट कर रहे हैं। state.updateIn(['files', index]) पर आपका अपडेटर कॉलबैक एक पैरामीटर के रूप में आपको ठीक उसी फ़ाइल ऑब्जेक्ट को वापस कर रहा है। https://facebook.github.io/immutable-js/docs/#/Map पर Immutable.js डॉक्स के अनुसार: अपडेटर समारोह एक ही मूल्य इसके साथ बुलाया गया था रिटर्न

है, तो कोई परिवर्तन नहीं हो जाएगा। यह अभी भी सत्य है अगर SetValue प्रदान नहीं किया जाता है।

तो हाँ। आप वही वैल्यू लौट रहे हैं जो आपको दिया गया था, इसके लिए आपके प्रत्यक्ष उत्परिवर्तन DevTools में दिखाई दे रहे हैं क्योंकि वह ऑब्जेक्ट अभी भी आसपास लटक रहा है, लेकिन जब से आप एक ही ऑब्जेक्ट लौटाते हैं तो Immutable.js वास्तव में किसी संशोधित ऑब्जेक्ट को वापस नहीं कर रहा है पदानुक्रम इसलिए, जब रेडक्स शीर्ष-स्तरीय ऑब्जेक्ट पर चेक करता है, तो यह देखता है कि कुछ भी नहीं बदला है, ग्राहकों को सूचित नहीं करता है, और इसलिए आपके घटक का mapStateToProps कभी नहीं चलता है।

अपने reducer को साफ करें और उस अद्यतनकर्ता के अंदर से एक नई वस्तु वापस करें, और सभी बस काम करें।

(ए बल्कि देर से लिया गया जवाब है, लेकिन मैं अभी-अभी सवाल को देखा, और यह अभी भी खुला हो गया लगता है। उम्मीद है कि आप वास्तव में मिल गया यह अब तक तय हो गई ...)

+0

अरे, क्षमा करें मैंने इसका जवाब नहीं दिया है। मैं वर्तमान में प्रतिक्रिया/Redux और अन्य मॉड्यूल उन्नयन कर रहा हूँ। मैं इस सप्ताह के अंत में कोशिश करूँगा और आपको वापस ले जाऊंगा। विस्तृत उत्तर के लिए धन्यवाद! –

+1

मुझे उन परिवर्तनों को लागू करने के लिए दौर मिला जो आपने मुझे इंगित किया और यह सबकुछ हल हो गया। आपकी सहायताके लिए धन्यवाद! :) –

+0

@ChrisPaton क्या आप कृपया अपने प्रासंगिक परिवर्तन साझा कर सकते हैं? –

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

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