एक बच्चे के घटक के अंदर से रिएक्ट संदर्भ कैसे अपडेट करें?


109

मेरे पास नीचे की तरह संदर्भ में भाषा सेटिंग्स हैं

class LanguageProvider extends Component {
  static childContextTypes = {
    langConfig: PropTypes.object,
  };

  getChildContext() {
    return { langConfig: 'en' };
  }

  render() {
    return this.props.children;
  }
}

export default LanguageProvider;

मेरा आवेदन कोड नीचे की तरह कुछ होगा

<LanguageProvider>
  <App>
    <MyPage />
  </App>
</LanguageProvider>

मेरा पृष्ठ भाषा स्विच करने के लिए एक घटक है

<MyPage>
  <LanguageSwitcher/>
</MyPage>

LanguageSwitcher इस में MyPageजरूरत संदर्भ अद्यतन करने के लिए नीचे के रूप में 'जेपी' में भाषा बदलने के लिए

class LanguageSwitcher extends Component {
  static contextTypes = {
    langConfig: PropTypes.object,
  };

  updateLanguage() {
    //Here I need to update the langConfig to 'jp' 
  }

  render() {
    return <button onClick={this.updateLanguage}>Change Language</button>;
  }
}

export default LanguageSwitcher;

मैं LanguageSwitcher घटक के अंदर से संदर्भ को कैसे अपडेट कर सकता हूं?


क्या आपने इसे पढ़ा है? facebook.github.io/react/docs/context.html#updating-context शायद यह कुछ और अच्छी तरह से राज्य के संदर्भ के लिए अनुकूल नहीं है
azium

@azium हां .. उस डॉक्टर में संदर्भ घटक से ही अपडेट किया जाता है या डॉक में जोड़ा गया ब्लॉग लिंक होता है, जिसमें संदर्भ प्रदाता के पास एक सहारा के रूप में दिया गया संदर्भ होता है, मुझे इसे बाल घटक से अपडेट करने की आवश्यकता होती है
mshameer

यदि आपको इसे अपडेट करने की आवश्यकता नहीं है तो Uhh कोई दस्तावेज़ संदर्भ का उपयोग नहीं करने के लिए कहता है। "ऐसा मत करो" सटीक होने के लिए। मैं फिर से
दोहराऊंगा

2
@LondonRob आप किस तरह के विहित जवाब की तलाश कर रहे हैं? IMO डॉक्स की सामग्री मुझे ठीक लगती है। यदि आप एक बच्चे में संदर्भ सेट करना चाहते हैं, तो बस प्रदाता के घटक में एक सेटर बनाएं और एक बाल उपभोक्ता को पास करें। फिर उस सेटर को चाइल्ड कंज्यूमर में कॉल करें और उसे सेट करें कि बच्चे के अंदर जो भी डाटा है। फिर भी डेटा उठाने के रिएक्ट के विचार के साथ रहता है।
एंड्रयू ली

2
@azium इन वर्षों में यह टिप्पणी पढ़ने वाले अन्य लोगों के लिए सिर्फ एक सिर है। : एक बच्चे के घटक से संदर्भ अद्यतन कर रहा है अब समर्थित है और काफी सरल hyp.is/FiP3mG6fEeqJiOfWzfKpgw/reactjs.org/docs/context.html
lustig

जवाबों:


249

हुक का उपयोग करना

हुक 16.8.0 में पेश किए गए थे, इसलिए निम्न कोड को 16.8.0 के न्यूनतम संस्करण की आवश्यकता होती है (वर्ग घटकों के उदाहरण के लिए नीचे स्क्रॉल करें)। CodeSandbox डेमो

1. गतिशील संदर्भ के लिए मूल स्थिति निर्धारित करना

सबसे पहले, एक गतिशील संदर्भ के लिए जो उपभोक्ताओं को पारित किया जा सकता है, मैं माता-पिता की स्थिति का उपयोग करूंगा। यह सुनिश्चित करता है कि मैं सच का एक ही स्रोत जा रहा हूं। उदाहरण के लिए, मेरा मूल एप्लिकेशन इस तरह दिखाई देगा:

const App = () => {
  const [language, setLanguage] = useState("en");
  const value = { language, setLanguage };

  return (
    ...
  );
};

languageराज्य में संग्रहित है। हम बाद में संदर्भ के माध्यम से दोनों languageऔर सेटर फ़ंक्शन को पास करेंगे setLanguage

2. एक प्रसंग बनाना

इसके बाद, मैंने इस तरह एक भाषा संदर्भ बनाया:

// set the defaults
const LanguageContext = React.createContext({
  language: "en",
  setLanguage: () => {}
});

यहां मैं language('एन') और एक setLanguageफ़ंक्शन के लिए डिफॉल्ट सेट कर रहा हूं, जो उपभोक्ता को संदर्भ प्रदाता द्वारा भेजा जाएगा। ये केवल डिफॉल्ट हैं और माता-पिता में प्रदाता घटक का उपयोग करते समय मैं उनके मूल्य प्रदान करूंगा App

नोट: LanguageContextवही रहता है चाहे आप हुक या वर्ग आधारित घटकों का उपयोग करें।

3. एक संदर्भ उपभोक्ता बनाना

भाषा स्विचर को भाषा सेट करने के लिए, इसे संदर्भ के माध्यम से भाषा सेटर फ़ंक्शन तक पहुंच होना चाहिए। यह कुछ इस तरह दिख सकता है:

const LanguageSwitcher = () => {
  const { language, setLanguage } = useContext(LanguageContext);
  return (
    <button onClick={() => setLanguage("jp")}>
      Switch Language (Current: {language})
    </button>
  );
};

यहाँ मैं सिर्फ भाषा को 'jp' में सेट कर रहा हूँ, लेकिन इसके लिए भाषा निर्धारित करने के लिए आपके पास अपने तर्क हो सकते हैं।

4. एक प्रदाता में उपभोक्ता को लपेटना

अब मैं अपनी भाषा स्विचर घटक को एक में प्रस्तुत करूँगा LanguageContext.Providerऔर उन मानों में पास करूँगा जिन्हें किसी भी स्तर तक संदर्भ के माध्यम से भेजा जाना है। यहां बताया गया है कि मेरे माता-पिता कैसे Appदिखते हैं:

const App = () => {
  const [language, setLanguage] = useState("en");
  const value = { language, setLanguage };

  return (
    <LanguageContext.Provider value={value}>
      <h2>Current Language: {language}</h2>
      <p>Click button to change to jp</p>
      <div>
        {/* Can be nested */}
        <LanguageSwitcher />
      </div>
    </LanguageContext.Provider>
  );
};

अब, जब भी भाषा स्विचर क्लिक किया जाता है, तो यह संदर्भ को गतिशील रूप से अपडेट करता है।

CodeSandbox डेमो

वर्ग घटकों का उपयोग करना

नवीनतम संदर्भ API को अभिक्रिया 16.3 में पेश किया गया था जो एक गतिशील संदर्भ होने का एक शानदार तरीका प्रदान करता है। निम्न कोड के लिए न्यूनतम 16.3.0 संस्करण की आवश्यकता होती है। CodeSandbox डेमो

1. गतिशील संदर्भ के लिए मूल स्थिति निर्धारित करना

सबसे पहले, एक गतिशील संदर्भ के लिए जो उपभोक्ताओं को पारित किया जा सकता है, मैं माता-पिता की स्थिति का उपयोग करूंगा। यह सुनिश्चित करता है कि मैं सच का एक ही स्रोत जा रहा हूं। उदाहरण के लिए, मेरा मूल एप्लिकेशन इस तरह दिखाई देगा:

class App extends Component {
  setLanguage = language => {
    this.setState({ language });
  };

  state = {
    language: "en",
    setLanguage: this.setLanguage
  };

  ...
}

languageएक भाषा सेटर विधि है, जो आप राज्य वृक्ष के बाहर रख सकते हैं के साथ-साथ राज्य में संग्रहित है।

2. एक प्रसंग बनाना

इसके बाद, मैंने इस तरह एक भाषा संदर्भ बनाया:

// set the defaults
const LanguageContext = React.createContext({
  language: "en",
  setLanguage: () => {}
});

यहां मैं language('एन') और एक setLanguageफ़ंक्शन के लिए डिफॉल्ट सेट कर रहा हूं, जो उपभोक्ता को संदर्भ प्रदाता द्वारा भेजा जाएगा। ये केवल डिफॉल्ट हैं और माता-पिता में प्रदाता घटक का उपयोग करते समय मैं उनके मूल्य प्रदान करूंगा App

3. एक संदर्भ उपभोक्ता बनाना

भाषा स्विचर को भाषा सेट करने के लिए, इसे संदर्भ के माध्यम से भाषा सेटर फ़ंक्शन तक पहुंच होना चाहिए। यह कुछ इस तरह दिख सकता है:

class LanguageSwitcher extends Component {
  render() {
    return (
      <LanguageContext.Consumer>
        {({ language, setLanguage }) => (
          <button onClick={() => setLanguage("jp")}>
            Switch Language (Current: {language})
          </button>
        )}
      </LanguageContext.Consumer>
    );
  }
}

यहाँ मैं सिर्फ भाषा को 'jp' में सेट कर रहा हूँ, लेकिन इसके लिए भाषा निर्धारित करने के लिए आपके पास अपने तर्क हो सकते हैं।

4. एक प्रदाता में उपभोक्ता को लपेटना

अब मैं अपनी भाषा स्विचर घटक को एक में प्रस्तुत करूँगा LanguageContext.Providerऔर उन मानों में पास करूँगा जिन्हें किसी भी स्तर तक संदर्भ के माध्यम से भेजा जाना है। यहां बताया गया है कि मेरे माता-पिता कैसे Appदिखते हैं:

class App extends Component {
  setLanguage = language => {
    this.setState({ language });
  };

  state = {
    language: "en",
    setLanguage: this.setLanguage
  };

  render() {
    return (
      <LanguageContext.Provider value={this.state}>
        <h2>Current Language: {this.state.language}</h2>
        <p>Click button to change to jp</p>
        <div>
          {/* Can be nested */}
          <LanguageSwitcher />
        </div>
      </LanguageContext.Provider>
    );
  }
}

अब, जब भी भाषा स्विचर क्लिक किया जाता है, तो यह संदर्भ को गतिशील रूप से अपडेट करता है।

CodeSandbox डेमो


आपके द्वारा संदर्भ को प्रारंभ करने वाले डिफ़ॉल्ट मानों का उद्देश्य क्या है? क्या उन चूक हमेशा से अधिक नहीं हैं Provider?
इको

@ecoe सही है, हालाँकि प्रदाता के न होने की स्थिति में value, उपभोक्ता द्वारा चूक का उपयोग किया जाएगा।
दिव्यांशु मैथानी

1
क्यों संदर्भों को एक सरल मूल्य निर्धारित करने / प्राप्त करने के लिए सीमित किया जा रहा है .... जो बहुत ही अक्षम लगता है। एक बेहतर उदाहरण एक ऐसे संदर्भ को उजागर करना होगा जो एक वस्तु के रूप में डिफ़ॉल्ट हो और वस्तु को तदनुसार अद्यतन करे।
AlxVallejo

1
टाइपस्क्रिप्ट मेरे मामले में शिकायत करती है यदि सेट लैंग्वेज में कोई पैरामीटर नहीं है। setLanguage: (language: string) => {}मेरे लिये कार्य करता है।
एलेक्स 351

1
इसके लिए शुक्रिया। यह स्पष्ट हो गया है कि किस तरह से मुझे अपने बालों को खींचना नहीं चाहिए।
c0dezer019

49

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

LanguageContextMangement.js

import React, { useState } from 'react'

export const LanguageContext = React.createContext({
  language: "en",
  setLanguage: () => {}
})

export const LanguageContextProvider = (props) => {

  const setLanguage = (language) => {
    setState({...state, language: language})
  }

  const initState = {
    language: "en",
    setLanguage: setLanguage
  } 

  const [state, setState] = useState(initState)

  return (
    <LanguageContext.Provider value={state}>
      {props.children}
    </LanguageContext.Provider>
  )
}

App.js

import React, { useContext } from 'react'
import { LanguageContextProvider, LanguageContext } from './LanguageContextManagement'

function App() {

  const state = useContext(LanguageContext)

  return (
    <LanguageContextProvider>
      <button onClick={() => state.setLanguage('pk')}>
        Current Language is: {state.language}
      </button>
    </LanguageContextProvider>
  )
}

export default App

1
मैं यह कर रहा हूं और मेरे बच्चे के घटक के अंदर मेरा सेट फंक्शन हमेशा वह है जिसे हमने शुरू में संदर्भ बनाते समय घोषित किया था:() => {}
एलेजांद्रो कोरिडोर

5
स्पष्ट करने के लिए, मुझे लगता है कि आपके उदाहरण में state.setLanguage('pk')कुछ भी नहीं होगा, क्योंकि const state = useContext(LanguageContext)बाहर है LanguageContextProvider। मैंने प्रदाता को एक स्तर ऊपर और फिर useContextएक बच्चे के नीचे एक स्तर का उपयोग करके अपनी समस्या हल की।
एलेजांद्रो कोरिडोर

2
मामले में आप अपने संदर्भ प्रदाता एक स्तर ऊपर ले जाने के लिए भी इस तरह संदर्भ उपभोक्ता उपयोग कर सकते हैं नहीं करना चाहते हैं: <LanguageContext.Consumer> {value => /* access your value here */} </LanguageContext.Consumer>
मेटेन कीनी

3
मैं वास्तव में LanguageContextMangement.js फ़ाइल को व्यवस्थित करने के तरीके को पसंद करता हूं। यह मेरी राय में चीजों को करने का एक साफ तरीका है और मैं अब ऐसा करने जा रहा हूं। धन्यवाद!
lustig

2
सराहना के लिए धन्यवाद यह वास्तव में मुझे इस तरह काम करना जारी रखने के लिए प्रोत्साहित करता है!
मतीन कियानी

3

एक बहुत ही सरल उपाय यह है कि आप अपने प्रदाता में सेटस्टैट विधि को शामिल करके अपने संदर्भ में स्थिति निर्धारित करें:

return ( 
            <Context.Provider value={{
              state: this.state,
              updateLanguage: (returnVal) => {
                this.setState({
                  language: returnVal
                })
              }
            }}> 
              {this.props.children} 
            </Context.Provider>
        )

और अपने उपभोक्ता में, कॉल अपडेट को लाइक करें:

// button that sets language config
<Context.Consumer>
{(context) => 
  <button onClick={context.updateLanguage({language})}> 
    Set to {language} // if you have a dynamic val for language
  </button>
<Context.Consumer>
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.