2016-04-14 6 views
10

मैं react & redux का उपयोग कर आवेदन पर काम कर रहा हूं और मुझे सेटप्रॉप की आवश्यकता है लेकिन यह बहिष्कृत है।प्रतिक्रिया में setProps का उपयोग करने से कैसे बचें?

चेतावनी::

नीचे एक नज़र त्रुटि लो setProps (...) और replaceProps (...) पदावनत कर रहे हैं। इसके बजाय, कॉल शीर्ष स्तर पर फिर से प्रस्तुत करें।

अनचाहे Invariant उल्लंघन: setProps (...): setProps पर पर एक माता-पिता के साथ एक घटक कहा जाता है। यह एक विरोधी पैटर्न है क्योंकि प्रोप प्रदान किए जाने पर प्रतिक्रियात्मक रूप से अपडेट हो जाएंगे। इसके बजाए, घटक render विधि को सही मान पास करने के लिए घटक पर प्रोप के रूप में बदलें जहां इसे बनाया गया है।

तो मैं प्रोप कैसे सेट कर सकता हूं? मूल रूप से, कुछ टैब का प्रबंधन मेरे कोड के नीचे एक नज़र रखना है:

export default React.createClass({ 
    render: function() { 
    return (
     <div className="demo-tabs"> 
      <Tabs activeTab={this.props.activeTab} 
        onChange={(tabId) => this.setProps({ activeTab: tabId })} ripple> 
       <Tab>Stack</Tab> 
       <Tab>GitHub</Tab> 
       <Tab>Twitter</Tab> 
      </Tabs> 
      <section> 
       <div className="content">Content for the tab: {this.props.activeTab}</div> 
      </section> 
     </div> 
    ); 
    } 
}); 

कंटेनर

import React from 'react'; 
import TimeLine from './timeline'; 
import { connect } from 'react-redux'; 
import { getStackoverflow } from 'api/timeline'; 

const TimeLineContainer = React.createClass({ 

    componentWillMount: function() { 
     getStackoverflow(); 
    }, 

    render: function() { 
     return (
      <TimeLine {...this.props} /> 
     ) 
    } 
}); 

const stateToProps = function(state) { 
    return { 
     timeline: state.timelineReducer.timeline 
    } 
} 

const dispatchToProps = function(dispatch) { 
    return { 
     onClick:() => {console.log('timeline was clicked')} 
    } 
} 

export default connect(stateToProps, dispatchToProps)(TimeLineContainer) 

प्रसारण

var timelineInitialState = { 
    github:   [], 
    gist:   [], 
    stackoverflow: [], 
    twitter:  [], 
    activeTab:  2 
} 

export default function(state = timelineInitialState, action) { 
    switch (action.type) { 
    case 'GET_GITHUB': 
     //TODO: implement. 
     break; 
    case 'GET_GIST': 
     //TODO: implement. 
     break; 
    case 'GET_STACKOVERFLOW': 
     var stackoverflowState = Object.assign({}, state) 
     stackoverflowState.stackoverflow = action.stackoverflow; 
     return stackoverflowState; 
     break; 
    case 'GET_TWITTER': 
     //TODO: implement. 
     break; 
    default: 
     return state; 
    } 
} 
+2

ऐसा लगता है कि आपको खुद को स्थापित करने के लिए आवश्यक प्रोप की तरह आंतरिक स्थिति होना चाहिए और आपको इसके बजाय सेटस्टेट को कॉल करना चाहिए। या प्रोप को रखें, लेकिन इसे बदलते समय राज्य को सेट करें (सिंक प्रोप और स्टेट) –

+0

@JuanMendes की तरह, आप राज्य का उपयोग करना चाहेंगे। आप क्या कर सकते हैं अपने प्रोप का उपयोग करके अपना प्रारंभिक राज्य सेट करें और फिर अपडेट किए गए मान को –

+0

@realseanp पर सेट करें, आपको यह सुनिश्चित करना होगा कि आप 'घटकWillReceiveProps' को लागू करते हैं, इसलिए यह स्थिति अद्यतन करता है जब मूल घटक प्रारंभिक के बाद प्रोप सेट करता है प्रस्तुत करना –

उत्तर

44

ऐसा लगता है कि आप पहली बार प्रतिक्रिया की पकड़ मजबूत हो रही बिना Redux का उपयोग कर में डुबकी लगाई। मैं ऐसा करने की सिफारिश नहीं करता क्योंकि आप अब कुछ उलझन में दिख रहे हैं।

Thinking in React एक महान गाइड है और मैं आपको पहले इसे जाने और रेडक्स का उपयोग करने से पहले, प्रतिक्रिया में राज्य स्वामित्व के विचार से सहज महसूस करने की सलाह देता हूं।

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

यहां महत्वपूर्ण हिस्सा यह है कि props माता-पिता द्वारा प्राप्त किया जाना है।एक घटक अपने स्वयं के रंगमंच की सामग्री को बदलना चाहता है, तो यह एक समस्या का एक लक्षण है:

  1. या तो आप इस घटक के लिए state का इस्तेमाल किया है चाहिए, ताकि आप setState
  2. कॉल कर सकते हैं या अपने घटक एक कॉलबैक का उपयोग करने की जरूरत है प्रोप की तरह onChange तो यह "पूछना" कर सकते हैं मूल्य

पहले मामले में परिवर्तित करने की, अपने कोड इस प्रकार दिखाई देगा, और यह वैध होगा प्रतिक्रिया:

export default React.createClass({ 
    getInitialState: function() { 
    return { activeTab: 0 } 
    }, 

    render: function() { 
    return (
     <div className="demo-tabs"> 
      <Tabs activeTab={this.state.activeTab} 
        onChange={(tabId) => this.setState({ activeTab: tabId })} ripple> 
       <Tab>Stack</Tab> 
       <Tab>GitHub</Tab> 
       <Tab>Twitter</Tab> 
      </Tabs> 
      <section> 
       <div className="content">Content for the tab: {this.state.activeTab}</div> 
      </section> 
     </div> 
    ); 
    } 
}); 

हालांकि, आप उस पैटर्न को जारी रख सकते हैं जिसका आप पहले से ही <Tabs> घटक के साथ उपयोग कर रहे हैं, और राज्य को और भी ऊंचा कर सकते हैं। फिर आपके घटक को onChange प्रोप को स्वीकार करने की आवश्यकता होगी जो इसे <Tabs> तक पारित कर देगी। अब यह यह नहीं पता कि राज्य अद्यतन किया जाता है, और राज्य नहीं रखता है:

export default React.createClass({ 
    render: function() { 
    return (
     <div className="demo-tabs"> 
      <Tabs activeTab={this.props.activeTab} 
        onChange={this.props.onChange} ripple> 
       <Tab>Stack</Tab> 
       <Tab>GitHub</Tab> 
       <Tab>Twitter</Tab> 
      </Tabs> 
      <section> 
       <div className="content">Content for the tab: {this.props.activeTab}</div> 
      </section> 
     </div> 
    ); 
    } 
}); 

न तो दृष्टिकोण बेहतर या बदतर है, वे विभिन्न प्रयोजनों के लिए उपयोग किया जाता है। पहला एक और सुविधाजनक है जब राज्य शेष ऐप के लिए अप्रासंगिक है, दूसरा सुविधाजनक है जब अन्य दूरस्थ घटकों को भी इसकी आवश्यकता होती है। सुनिश्चित करें कि आप दोनों दृष्टिकोणों के व्यापारिक समझौते को समझते हैं।

दूसरे दृष्टिकोण के साथ भी, कुछ को राज्य को पकड़ना है। यह एक और घटक हो सकता है, या (और यह वह जगह है जहां रेडक्स आता है) यह रेडक्स स्टोर की तरह एक अलग डेटा स्टोरेज हो सकता है। इस मामले में, के बजाय एक माता पिता के घटक से onChange की आपूर्ति, आप connect() का प्रयोग करेंगे एक onChange बाँध सहारा यह एक Redux कार्रवाई डिस्पैच करने के इंजेक्शन के लिए:

const mapStateToProps = (state) => { 
    return { 
    activeTabId: state.activeTabId 
    } 
} 

const mapDispatchToProps = (dispatch) => { 
    return { 
    onChange: (tabId) => dispatch({ type: 'SET_ACTIVE_TAB', tabId }) 
    } 
} 

और अपने reducers में, आप इस क्रिया को प्रबंधित कर सकते हैं:

const activeTabId = (state = 0, action) => { 
    switch (action.type) { 
    case 'SET_ACTIVE_TAB': 
    return action.tabId 
    default: 
    return state 
    } 
} 

const reducer = combineReducers({ 
    activeTabId, 
    // other reducers 
}) 

const store = createStore(reducer) 

किसी भी मामले में हमें setProps की आवश्यकता नहीं है। आप या तो:

  • घटक राज्य के मालिक हैं और setState का उपयोग करते हैं,
  • यह activeTabId और onChange रंगमंच की सामग्री को स्वीकार करते हैं और उन्हें एक घटक पेड़ में उच्च कि setState का प्रयोग करेंगे, या
  • से प्रबंधन आप रेडक्स जैसे कुछ घटकों से पूरी तरह से राज्य को संभालने में स्थानांतरित कर सकते हैं, लेकिन आपके घटक अभी भी activeTabId और onChange प्रोप के रूप में स्वीकार करेंगे।
2

कंटेनर से समय घटक को onTabChange कॉलबैक प्रदान करें।

कंटेनर:

const dispatchToProps = function(dispatch) { 
    return { 
     onClick:() => {console.log('timeline was clicked')}, 
     onTabChange: (tabId) => { setActiveTabAction(tabId) } 
    } 
} 
const stateToProps = function(state) { 
    return { 
     timeline: state.timelineReducer.timeline, 
     activeTab: state.timelineReducer.activeTab 
    } 
} 

समय घटक:

export default React.createClass({ 
    render: function() { 
    return (
     <div className="demo-tabs"> 
      <Tabs activeTab={this.props.activeTab} 
        onChange={this.props.onTabChange} ripple> 
       <Tab>Stack</Tab> 
       <Tab>GitHub</Tab> 
       <Tab>Twitter</Tab> 
      </Tabs> 
      <section> 
       <div className="content">Content for the tab: {this.props.activeTab}</div> 
      </section> 
     </div> 
    ); 
    } 
}); 

(अपने समय घटक की तरह) प्रस्तुतिकरण घटक आम तौर पर आवेदन राज्य का प्रबंधन नहीं करना चाहिए। सभी डेटा और कॉलबैक उन्हें प्रोप द्वारा प्राप्त करना होगा।

मैं सुझाव है कि आप प्रस्तुतिकरण और कंटेनर घटकों के बारे में लेख पढ़ने के लिए: https://medium.com/@dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0#.sijqpzk93

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