रिएक्ट-रिडक्स और मैपस्टैटटॉप्रॉप्स () को समझना


220

मैं प्रतिक्रिया-रिडक्स की कनेक्ट विधि को समझने की कोशिश कर रहा हूं, और फ़ंक्शन जो पैरामीटर के रूप में लेता है। विशेष रूप से mapStateToProps()

जिस तरह से मैं इसे समझता हूं, वापसी का मूल्य mapStateToPropsराज्य से प्राप्त एक वस्तु होगा (जैसा कि यह स्टोर में रहता है), जिसकी कुंजी आपके लक्ष्य घटक (घटक कनेक्ट लागू होती है) को प्रॉपर के रूप में पास की जाएगी।

इसका मतलब यह है कि आपके लक्षित घटक द्वारा खपत की गई स्थिति में राज्य से एक बेतहाशा अलग संरचना हो सकती है क्योंकि यह आपके स्टोर पर संग्रहीत है।

प्रश्न: क्या यह ठीक है?
प्रश्न: क्या यह अपेक्षित है?
क्यू: यह एक विरोधी पैटर्न है?


11
मैं मिश्रण करने के लिए एक और जवाब में जोड़ने के लिए नहीं करना चाहते हैं ... लेकिन मैं कोई भी वास्तव में अपने सवाल का जवाब ... मेरी राय में, यह पता ही नहीं एक विरोधी पैटर्न। कुंजी नाम में है MapStateTo Props आप एक घटक को उपभोग करने के लिए केवल-पढ़ने के लिए गुण पास कर रहे हैं। मैं अक्सर अपने कंटेनर घटकों का उपयोग राज्य को लेने और प्रस्तुति घटक में पास करने से पहले इसे बदलने के लिए करूंगा।
मैथ्यू ब्रेंट

3
इस तरह मेरा प्रस्तुतिकरण घटक बहुत सरल है ... मैं this.props.someDataविरोध कर सकता हूँ this.props.someKey[someOtherKey].someData... समझ में आता है?
मैथ्यू ब्रेंट

3
यह ट्यूटोरियल इसे अच्छी तरह से समझाता है: learn.co/lessons/map-state-to-props-readme
Ayan

हाय पाब्लो, कृपया अपने चुने हुए उत्तर पर फिर से विचार करें।
vsync

फिर से विचार करें कैसे?
पाब्लो बैरिया उरेंडा

जवाबों:


56

क्यू: Is this ok?
हाँ। हाँ

प्रश्न: Is this expected?
हां, यह अपेक्षित है (यदि आप प्रतिक्रिया-रिडक्स का उपयोग कर रहे हैं)।

क्यू: Is this an anti-pattern?
ए: नहीं, यह एक विरोधी पैटर्न नहीं है।

इसे आपके घटक को "कनेक्ट करना" या "इसे स्मार्ट बनाना" कहा जाता है। यह डिजाइन द्वारा है।

यह आपको अपने घटक को अपने राज्य से अतिरिक्त समय के लिए अलग करने की अनुमति देता है जो आपके कोड के प्रतिरूपकता को बढ़ाता है। यह आपको अपने घटक राज्य को आपके एप्लिकेशन राज्य के सबसेट के रूप में सरल बनाने की अनुमति देता है, जो वास्तव में, आपको Redux पैटर्न का अनुपालन करने में मदद करता है।

इसके बारे में इस तरह से सोचें: एक स्टोर में आपके आवेदन की संपूर्ण स्थिति शामिल होनी चाहिए ।
बड़े अनुप्रयोगों के लिए, इसमें दर्जनों संपत्तियां हो सकती हैं, जिनमें कई परतें गहरी होती हैं।
आप प्रत्येक कॉल (महंगी) के आसपास यह सब नहीं चाहते हैं।

इसके बिना mapStateToPropsया कुछ अनुरूप, आपको प्रदर्शन में सुधार / सरलीकरण के लिए अपने राज्य को एक और तरीके से उकेरने के लिए लुभाया जाएगा।


6
मुझे नहीं लगता कि प्रत्येक और हर घटक को पूरे स्टोर तक पहुंच प्रदान करना, हालांकि यह बड़ा हो सकता है, प्रदर्शन के साथ कुछ भी करना है। आस-पास से गुजरने वाली वस्तुओं की स्मृति नहीं होती है क्योंकि यह हमेशा एक ही वस्तु होती है। एकमात्र कारण घटकों के लिए आवश्यक भागों को लाने के लिए शायद 2 कारण हैं: (1) -आसान गहरी पहुंच उन (2) -कीड़ों से बचें जहां एक घटक गड़बड़ कर सकता है राज्य से संबंधित नहीं
vsync

@vsync क्या आप बता सकते हैं कि यह आसान गहरी पहुँच कैसे सक्षम करता है? क्या आपका मतलब है कि वैश्विक राज्य को संदर्भित करने के बजाय स्थानीय प्रॉप्स का उपयोग किया जा सकता है और इसलिए यह अधिक पठनीय है?
सिद्धार्थ

इसके अलावा, जब राज्य अपरिवर्तनीय रूप से पारित हो जाता है, तो घटक इससे संबंधित नहीं हो सकता है?
सिद्धार्थ

यदि राज्य अपरिवर्तनीय है, तो मुझे लगता है कि यह ठीक है, लेकिन फिर भी, अच्छे अभ्यास के रूप में, केवल उनके लिए प्रासंगिक भागों के घटकों को उजागर करना बेहतर है। यह अन्य डेवलपर्स को यह समझने में भी मदद करता है कि कौन से हिस्से ( राज्य वस्तु के) उस घटक के लिए प्रासंगिक हैं। "आसान पहुंच" के बारे में, यह इस अर्थ में आसान है कि कुछ गहरे राज्य का रास्ता सीधे घटक को एक प्रस्ताव के रूप में पारित किया जाता है, और यह घटक इस तथ्य से अंधा होता है कि पर्दे के पीछे Redux। अवयवों को परवाह नहीं करनी चाहिए कि किस राज्य प्रबंधन प्रणाली का उपयोग किया जाता है, और उन्हें केवल प्राप्त प्रॉप्स के साथ काम करना चाहिए।
vsync

119

हाँ यह सही है। अपने राज्य गुणों का उपयोग करने का एक सरल तरीका होने के लिए यह सिर्फ एक सहायक कार्य है

कल्पना कीजिए कि postsआपके ऐप में एक कुंजी हैstate.posts

state.posts //
/*    
{
  currentPostId: "",
  isFetching: false,
  allPosts: {}
}
*/

और घटक Posts

डिफ़ॉल्ट रूप connect()(Posts)से जुड़े हुए घटक के लिए सभी राज्य सहारा उपलब्ध कराएंगे

const Posts = ({posts}) => (
  <div>
    {/* access posts.isFetching, access posts.allPosts */}
  </div> 
)

अब जब आप state.postsअपने कंपोनेंट को मैप करते हैं तो यह थोड़ा अच्छा हो जाता है

const Posts = ({isFetching, allPosts}) => (
  <div>
    {/* access isFetching, allPosts directly */}
  </div> 
)

connect(
  state => state.posts
)(Posts)

mapDispatchToProps

आम तौर पर आपको लिखना होगा dispatch(anActionCreator())

साथ bindActionCreatorsआप यह भी अधिक आसानी से कर सकते हैं

connect(
  state => state.posts,
  dispatch => bindActionCreators({fetchPosts, deletePost}, dispatch)
)(Posts)

अब आप इसे अपने घटक में उपयोग कर सकते हैं

const Posts = ({isFetching, allPosts, fetchPosts, deletePost }) => (
  <div>
    <button onClick={() => fetchPosts()} />Fetch posts</button>
    {/* access isFetching, allPosts directly */}
  </div> 
)

एक्शन क्रिएटर्स पर अपडेट करें ..

एक्शन क्रिएटर का एक उदाहरण: deletePost

const deletePostAction = (id) => ({
  action: 'DELETE_POST',
  payload: { id },
})

तो, bindActionCreatorsबस अपने कार्यों को ले जाएगा, उन्हें dispatchकॉल में लपेटें । (मैंने redux का सोर्स कोड नहीं पढ़ा है, लेकिन कार्यान्वयन कुछ इस तरह दिख सकता है:

const bindActionCreators = (actions, dispatch) => {
  return Object.keys(actions).reduce(actionsMap, actionNameInProps => {
    actionsMap[actionNameInProps] = (...args) => dispatch(actions[actionNameInProps].call(null, ...args))
    return actionsMap;
  }, {})
}

मुझे लगता है कि मैं कुछ याद सकता है, लेकिन जहां करता dispatch => bindActionCreators({fetchPosts, deletePost}, dispatch)हो जाता है fetchPostsऔर deletePostकार्रवाई से पारित कर दिया?
इलियो

@ लियो ये आपके एक्शन क्रिएटर हैं, आपको इन्हें इम्पोर्ट करना है
webdeb

2
अच्छा उत्तर! मुझे लगता है कि यह ज़ोर देना अच्छा है कि कोड का यह हिस्सा state => state.posts( mapStateToPropsफ़ंक्शन) रिएक्ट को बताएगा कि अपडेट किए जाने पर क्या घटक फिर से रेंडर करेगा।
मिगेल पेरेस

38

आपको पहला भाग सही मिला:

हाँ mapStateToPropsमें स्टोर राज्य एक तर्क / परम के रूप में (द्वारा प्रदान किया गया है react-redux::connect) और इसका उपयोग स्टोर राज्य के कुछ भाग के साथ घटक को जोड़ने के लिए किया गया है।

जोड़ने से मेरा मतलब है कि लौटी हुई वस्तु mapStateToPropsको निर्माण समय पर सहारा के रूप में प्रदान किया जाएगा और बाद में कोई भी परिवर्तन उपलब्ध होगा componentWillReceiveProps

यदि आप ऑब्जर्वर डिजाइन पैटर्न को जानते हैं, तो यह ठीक उसी प्रकार है या इसके छोटे रूपांतर हैं।

एक उदाहरण चीजों को स्पष्ट करने में मदद करेगा:

import React, {
    Component,
} from 'react-native';

class ItemsContainer extends Component {
    constructor(props) {
        super(props);

        this.state = {
            items: props.items, //provided by connect@mapStateToProps
            filteredItems: this.filterItems(props.items, props.filters),
        };
    }

    componentWillReceiveProps(nextProps) {
        this.setState({
            filteredItems: this.filterItems(this.state.items, nextProps.filters),
        });
    }

    filterItems = (items, filters) => { /* return filtered list */ }

    render() {
        return (
            <View>
                // display the filtered items
            </View>
        );
    }
}

module.exports = connect(
    //mapStateToProps,
    (state) => ({
        items: state.App.Items.List,
        filters: state.App.Items.Filters,
        //the State.App & state.App.Items.List/Filters are reducers used as an example.
    })
    // mapDispatchToProps,  that's another subject
)(ItemsContainer);

एक अन्य प्रतिक्रिया घटक हो सकता है जिसे itemsFiltersडिस्प्ले को हैंडल करना और फ़िल्टर स्थिति को Redux Store स्थिति में बनाए रखना है, डेमो घटक Redux Store राज्य फ़िल्टर को "सुन" या "सब्सक्राइब्ड" किया जाता है, इसलिए जब भी फ़िल्टर स्टोर में राज्य परिवर्तन ( filtersComponentप्रतिक्रिया की मदद से ) प्रतिक्रिया करता है -आर्डक्स यह पता लगाता है कि परिवर्तन और सूचना या "प्रकाशित" सभी सुन / सब्सक्राइब किए गए घटकों को उनके परिवर्तनों को भेजकर, componentWillReceivePropsजो इस उदाहरण में हैं, वस्तुओं के एक परिशोधक को ट्रिगर करेंगे और इस तथ्य के कारण प्रदर्शन को ताज़ा करेंगे कि प्रतिक्रिया की स्थिति बदल गई है ।

मुझे बताएं कि क्या उदाहरण भ्रमित कर रहा है या बेहतर स्पष्टीकरण प्रदान करने के लिए पर्याप्त स्पष्ट नहीं है।

यथा: इसका मतलब यह है कि आपके लक्षित घटक द्वारा खपत की गई अवस्था में राज्य से अलग-अलग संरचना हो सकती है क्योंकि यह आपके स्टोर पर संग्रहीत है।

मुझे सवाल नहीं मिला, लेकिन सिर्फ इतना पता है कि प्रतिक्रिया राज्य ( this.setState) Redux Store राज्य से पूरी तरह से अलग है!

प्रतिक्रिया अवस्था का उपयोग अभिक्रिया घटक के रिड्रा और व्यवहार को संभालने के लिए किया जाता है। प्रतिक्रिया राज्य घटक के लिए विशेष रूप से निहित है।

Redux Store राज्य Redux Reducers राज्यों का एक संयोजन है, प्रत्येक एक छोटे से हिस्से ऐप लॉजिक को प्रबंधित करने के लिए जिम्मेदार है। उन reducers विशेषताएँ react-redux::connect@mapStateToPropsकिसी भी घटक की मदद से पहुँचा जा सकता है ! जो कि Redux स्टोर राज्य को सुलभ ऐप व्यापक बनाता है जबकि घटक राज्य अपने आप में अनन्य है।


5

यह प्रतिक्रिया और रिडक्स उदाहरण मोहम्मद मेलौकी के उदाहरण पर आधारित है। लेकिन प्रीटेटिफाइ और लिनिंग नियमों का उपयोग करके मान्य होता है । ध्यान दें कि हम अपने रंगमंच की सामग्री और परिभाषित प्रेषण तरीकों का उपयोग कर PropTypes ताकि हमारे संकलक हमें चीख नहीं करता है। इस उदाहरण में कोड की कुछ लाइनें भी शामिल थीं जो मोहम्मद के उदाहरण में गायब थीं। कनेक्ट का उपयोग करने के लिए आपको इसे प्रतिक्रिया-रिडक्स से आयात करना होगा । यह उदाहरण विधि फ़िल्टर को भी बांधता है । यह घटक में गुंजाइश की समस्याओं को रोक देगा । यह स्रोत कोड जावास्क्रिप्ट प्रीटेट का उपयोग करके ऑटो स्वरूपित किया गया है ।

import React, { Component } from 'react-native';
import { connect } from 'react-redux';
import PropTypes from 'prop-types';

class ItemsContainer extends Component {
  constructor(props) {
    super(props);
    const { items, filters } = props;
    this.state = {
      items,
      filteredItems: filterItems(items, filters),
    };
    this.filterItems = this.filterItems.bind(this);
  }

  componentWillReceiveProps(nextProps) {
    const { itmes } = this.state;
    const { filters } = nextProps;
    this.setState({ filteredItems: filterItems(items, filters) });
  }

  filterItems = (items, filters) => {
    /* return filtered list */
  };

  render() {
    return <View>/*display the filtered items */</View>;
  }
}

/*
define dispatch methods in propTypes so that they are validated.
*/
ItemsContainer.propTypes = {
  items: PropTypes.array.isRequired,
  filters: PropTypes.array.isRequired,
  onMyAction: PropTypes.func.isRequired,
};

/*
map state to props
*/
const mapStateToProps = state => ({
  items: state.App.Items.List,
  filters: state.App.Items.Filters,
});

/*
connect dispatch to props so that you can call the methods from the active props scope.
The defined method `onMyAction` can be called in the scope of the componets props.
*/
const mapDispatchToProps = dispatch => ({
  onMyAction: value => {
    dispatch(() => console.log(`${value}`));
  },
});

/* clean way of setting up the connect. */
export default connect(mapStateToProps, mapDispatchToProps)(ItemsContainer);

यह उदाहरण कोड आपके घटक के लिए एक शुरुआती जगह के लिए एक अच्छा टेम्पलेट है।


2

React-Redux connect का उपयोग हर क्रिया के लिए स्टोर को अपडेट करने के लिए किया जाता है।

import { connect } from 'react-redux';

const AppContainer = connect(  
  mapStateToProps,
  mapDispatchToProps
)(App);

export default AppContainer;

यह बहुत सरल और स्पष्ट रूप से इस ब्लॉग में समझाया गया है ।

आप Redux कनेक्ट को समझने के लिए उस ब्लॉग से github प्रोजेक्ट को क्लोन या कॉपी पेस्ट कर सकते हैं।


अच्छा मैनुअल formapStateToProps thegreatcodeadventure.com/...
zloctb

1

यहाँ के व्यवहार का वर्णन करने के लिए एक रूपरेखा / बॉयलरप्लेट है mapStateToProps:

(यह एक Redux कंटेनर क्या करता है का एक बहुत सरल सरलीकृत कार्यान्वयन है।)

class MyComponentContainer extends Component {
  mapStateToProps(state) {
    // this function is specific to this particular container
    return state.foo.bar;
  }

  render() {
    // This is how you get the current state from Redux,
    // and would be identical, no mater what mapStateToProps does
    const { state } = this.context.store.getState();

    const props = this.mapStateToProps(state);

    return <MyComponent {...this.props} {...props} />;
  }
}

और अगला

function buildReduxContainer(ChildComponentClass, mapStateToProps) {
  return class Container extends Component {
    render() {
      const { state } = this.context.store.getState();

      const props = mapStateToProps(state);

      return <ChildComponentClass {...this.props} {...props} />;
    }
  }
}

-2
import React from 'react';
import {connect} from 'react-redux';
import Userlist from './Userlist';

class Userdetails extends React.Component{

render(){
    return(
        <div>
            <p>Name : <span>{this.props.user.name}</span></p>
            <p>ID : <span>{this.props.user.id}</span></p>
            <p>Working : <span>{this.props.user.Working}</span></p>
            <p>Age : <span>{this.props.user.age}</span></p>
        </div>
    );
 }

}

 function mapStateToProps(state){  
  return {
    user:state.activeUser  
}

}

  export default connect(mapStateToProps, null)(Userdetails);
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.