रेंडर फ़ंक्शन के बाहर एक्सेस रिएक्ट संदर्भ


93

मैं Redux के बजाय नए React Context API का उपयोग करके एक नया ऐप विकसित कर रहा हूं, और इससे पहले, Reduxजब मुझे उदाहरण के लिए उपयोगकर्ताओं की सूची प्राप्त करने की आवश्यकता होती है, तो मैं बस componentDidMountअपनी कार्रवाई में कॉल करता हूं, लेकिन अब रिएक्ट संदर्भ के साथ, मेरे कार्य अंदर रहते हैं मेरा उपभोक्ता जो मेरे रेंडर फ़ंक्शन के अंदर है, जिसका अर्थ है कि हर बार मेरे रेंडर फ़ंक्शन को कॉल किया जाता है, यह मेरे उपयोगकर्ताओं की सूची प्राप्त करने के लिए मेरी कार्रवाई को कॉल करेगा और यह अच्छा नहीं है क्योंकि मैं बहुत सारे आवश्यक अनुरोध कर रहा हूं।

इसलिए, मैं अपनी कार्रवाई में केवल एक बार कॉल कैसे कर सकता हूं, जैसे componentDidMountकि रेंडर में कॉल करने के बजाय?

उदाहरण के लिए, इस कोड को देखें:

आइए मान लें कि मैं अपने सभी Providersको एक घटक में लपेट रहा हूं , जैसे:

import React from 'react';

import UserProvider from './UserProvider';
import PostProvider from './PostProvider';

export default class Provider extends React.Component {
  render(){
    return(
      <UserProvider>
        <PostProvider>
          {this.props.children}
        </PostProvider>
      </UserProvider>
    )
  }
}

फिर मैंने अपने सभी ऐप को इस तरह से प्रोवाइडर कंपोनेंट में डाला:

import React from 'react';
import Provider from './providers/Provider';
import { Router } from './Router';

export default class App extends React.Component {
  render() {
    const Component = Router();
    return(
      <Provider>
        <Component />
      </Provider>
    )
  }
}

अब, उदाहरण के लिए मेरे उपयोगकर्ता देखें, यह कुछ इस तरह होगा:

import React from 'react';
import UserContext from '../contexts/UserContext';

export default class Users extends React.Component {
  render(){
    return(
      <UserContext.Consumer>
        {({getUsers, users}) => {
          getUsers();
          return(
            <h1>Users</h1>
            <ul>
              {users.map(user) => (
                <li>{user.name}</li>
              )}
            </ul>
          )
        }}
      </UserContext.Consumer>
    )
  }
}

मुझे यह चाहिए:

import React from 'react';
import UserContext from '../contexts/UserContext';

export default class Users extends React.Component {
  componentDidMount(){
    this.props.getUsers();
  }

  render(){
    return(
      <UserContext.Consumer>
        {({users}) => {
          getUsers();
          return(
            <h1>Users</h1>
            <ul>
              {users.map(user) => (
                <li>{user.name}</li>
              )}
            </ul>
          )
        }}
      </UserContext.Consumer>
    )
  }
}

लेकिन यह कि ऊपर का उदाहरण काम नहीं करता है क्योंकि getUsersमेरे उपयोगकर्ता दृश्य में नहीं रहते हैं। यदि यह संभव है तो इसे करने का सही तरीका क्या है?

जवाबों:


143

EDIT: v16.8.0 में प्रतिक्रिया-हुक की शुरुआत के साथ , आप useContextहुक का उपयोग करके कार्यात्मक घटकों में संदर्भ का उपयोग कर सकते हैं

const Users = () => {
    const contextValue = useContext(UserContext);
    // rest logic here
}

संस्करण : 16.6.0 संस्करण के बाद से। आप का उपयोग करके जीवनचक्र विधि में संदर्भ का उपयोग कर सकते this.contextहैं

class Users extends React.Component {
  componentDidMount() {
    let value = this.context;
    /* perform a side-effect at mount using the value of UserContext */
  }
  componentDidUpdate() {
    let value = this.context;
    /* ... */
  }
  componentWillUnmount() {
    let value = this.context;
    /* ... */
  }
  render() {
    let value = this.context;
    /* render something based on the value of UserContext */
  }
}
Users.contextType = UserContext; // This part is important to access context values

संस्करण 16.6.0 से पहले, आप इसे निम्नलिखित तरीके से कर सकते हैं

अपने जीवन पद्धति में प्रसंग का उपयोग करने के लिए, आप अपने घटक की तरह लिखेंगे

class Users extends React.Component {
  componentDidMount(){
    this.props.getUsers();
  }

  render(){
    const { users } = this.props;
    return(

            <h1>Users</h1>
            <ul>
              {users.map(user) => (
                <li>{user.name}</li>
              )}
            </ul>
    )
  }
}
export default props => ( <UserContext.Consumer>
        {({users, getUsers}) => {
           return <Users {...props} users={users} getUsers={getUsers} />
        }}
      </UserContext.Consumer>
)

आम तौर पर आप अपने ऐप में एक संदर्भ को बनाए रखते हैं और यह एक एचओसी में उपरोक्त लॉगिन को पैकेज करने के लिए समझ में आता है ताकि इसका पुन: उपयोग किया जा सके। आप इसे लिख सकते हैं

import UserContext from 'path/to/UserContext';

const withUserContext = Component => {
  return props => {
    return (
      <UserContext.Consumer>
        {({users, getUsers}) => {
          return <Component {...props} users={users} getUsers={getUsers} />;
        }}
      </UserContext.Consumer>
    );
  };
};

और फिर आप इसे पसंद कर सकते हैं

export default withUserContext(User);

यह एक तरीका है! लेकिन मैं अपने घटकों को अन्य सामानों के साथ लपेट रहा हूं, इसलिए इस तरह से कोड अधिक से अधिक जटिल हो जाएगा। तो, संदर्भ के साथ पुस्तकालय का उपयोग करना और यह सज्जाकार कोड को और अधिक सरल बनाते हैं। लेकिन उत्तर के लिए धन्यवाद!
गुस्तावो मेंडोंका

यह मेरे लिए काम नहीं करता है, मैं संदर्भ गीथुब के साथ उपयोग करता हूं
पैशनट्यूबरडेलर

1
शुभम खत्री अपने जवाब में सही हैं, बस एक छोटा टाइपो है जो इसे चलाने से रोकता है। घुंघराले ब्रेस निहित प्रभाव को रोक रहे हैं। बस उन्हें कोष्ठक से बदल दें।
VDubs

1
क्या आप बता सकते हैं this.contextकि एक ही घटक के अंदर कई संदर्भों के साथ कैसे उपयोग किया जाए ? मान लीजिए कि मेरे पास एक घटक है जिसे UserContext और PostContext तक पहुंचने की आवश्यकता है, इसे कैसे संभालना है? मैं जो देख सकता हूं, वह दोनों को मिलाकर एक संदर्भ बनाना है, लेकिन इसके लिए एकमात्र या बेहतर समाधान क्या है?
गुस्तावो मेंडोंका

1
@ GustavoMendonça आप केवल इस संदर्भ का उपयोग करके एकल संदर्भ की सदस्यता ले सकते हैं। एपीआई कार्यान्वयन। यदि आपको एक से अधिक पढ़ने की आवश्यकता है तो आपको रेंडर प्रोप पैटर्न का पालन करने की आवश्यकता है
शुभम खत्री

3

ठीक है, मुझे एक सीमा के साथ ऐसा करने का एक तरीका मिला। with-contextलाइब्रेरी के साथ मैं अपने सभी उपभोक्ता डेटा को अपने घटक प्रॉपर में सम्मिलित करने में कामयाब रहा।

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

इस लाइब्रेरी का लिंक: https://github.com/SunHuawi/with-context

संपादित करें: वास्तव में आपको बहु संदर्भ एपि का उपयोग करने की आवश्यकता नहीं है with-context है, वास्तव में, आप सरल एपीआई का उपयोग कर सकते हैं और अपने प्रत्येक संदर्भ के लिए एक डेकोरेटर बना सकते हैं और यदि आप अपने घटक में एक से अधिक उपभोक्ता का उपयोग करना चाहते हैं, तो अपनी कक्षा के ऊपर जितना चाहे उतना डेकोरेटर घोषित करें!


1

मेरे हिस्से के लिए यह .bind(this)घटना में जोड़ने के लिए पर्याप्त था । इस तरह मेरा कंपोनेंट दिखता है।

// Stores File
class RootStore {
   //...States, etc
}
const myRootContext = React.createContext(new RootStore())
export default myRootContext;


// In Component
class MyComp extends Component {
  static contextType = myRootContext;

  doSomething() {
   console.log()
  }

  render() {
    return <button onClick={this.doSomething.bind(this)}></button>
  }
}

1
यह कोड बहुत सरल दिखता है, लेकिन यह वास्तव में मानों तक पहुंच नहीं करता है या रूटस्टोर उदाहरण के साथ अंतःक्रिया करता है। क्या आप दो फ़ाइलों और प्रतिक्रियाशील UI अद्यतनों में विभाजित एक उदाहरण दिखा सकते हैं?
Dcsan

-7

बच्चे में एक सहारा के रूप में उपयोग करने के लिए आपको उच्चतर मूल घटक में संदर्भ को पास करना होगा।

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