प्रतिक्रिया घटक के अंदर स्विच स्टेटमेंट का उपयोग कैसे करें?


108

मेरे पास एक प्रतिक्रिया घटक है, और घटक की renderविधि के अंदर मेरे पास कुछ इस तरह है:

render() {
    return (
        <div>
            <div>
                // removed for brevity
            </div>

           { switch(...) {} }

            <div>
                // removed for brevity
            </div>
        </div>
    );
}

अब मुद्दा यह है कि मेरे पास दो divतत्व हैं, एक शीर्ष पर और एक तल पर, यह तय है। बीच में मैं एक स्विच स्टेटमेंट रखना चाहता हूं, और अपने राज्य में एक मूल्य के अनुसार मैं एक अलग घटक प्रस्तुत करना चाहता हूं। इसलिए मूल रूप से, मैं चाहता हूं कि दो divतत्वों को हमेशा तय किया जाए, और हर बार एक अलग घटक को प्रस्तुत करने के लिए बीच में ही। मैं इसका उपयोग बहु-चरण भुगतान प्रक्रिया को लागू करने के लिए कर रहा हूं)। हालाँकि, जैसा कि वर्तमान में यह कोड काम नहीं कर रहा है, क्योंकि यह मुझे यह कहते हुए एक त्रुटि देता है कि switchयह अप्रत्याशित है। किसी भी विचार को कैसे प्राप्त करना है जो मुझे चाहिए?


1
ठीक है, आपको returnकथन में या renderउस बात के लिए विधि की भी सभी तर्क की आवश्यकता नहीं है। क्या आप प्रत्येक <div>को एक आधार के रूप में परिभाषित कर सकते हैं , और फिर अपने निर्धारित करने switch से पहले इसका उपयोग करना चाहिए जिसे प्रदान returnकिया <div>जाना चाहिए?
जेरेड गोगुएन

@JaredGoguen लेकिन फिर, मुझे divऊपर और नीचे, प्रत्येक मामले के लिए कई बार दोहराना होगा switch। या मैं गलत समझा, आप ..
टाइपो

नहीं, आप के लिए कोड बना सकते हैं let middleDiv = ...और फिर {middleDiv}दो <div>एस के बीच अपने रिटर्न जेएसएक्स में शामिल कर सकते हैं जिसे आपने हार्ड-कोडित किया है।
जेरेड गोगुएन

जवाबों:


199

इसे आज़माएं, जो कि क्लीनर भी है: एक फ़ंक्शन में रेंडर से बाहर स्विच करें और बस इसे आप चाहते हैं पासिंग को पास करें। उदाहरण के लिए:

renderSwitch(param) {
  switch(param) {
    case 'foo':
      return 'bar';
    default:
      return 'foo';
  }
}

render() {
  return (
    <div>
      <div>
          // removed for brevity
      </div>
      {this.renderSwitch(param)}
      <div>
          // removed for brevity
      </div>
    </div>
  );
}


92

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

render () {
  return (
    <div>
      <div>
        {/* removed for brevity */}
      </div>
      {
        {
          'foo': <Foo />,
          'bar': <Bar />
        }[param]
      }
      <div>
        {/* removed for brevity */}
      </div>
    </div>
  )
}

1
यह बहुत अच्छा है। मैंने POJO के बजाय एक सरणी का उपयोग करने के लिए इसे थोड़ा संशोधित किया और मैं केवल सरणी में ब्रैकेट के लिए सूचकांक का उपयोग कर रहा हूं।
निकोलस

1
यह पायथन में स्विच-केस को संभालने का मानक तरीका है। इसकी बेहतर पठनीयता के कारण मुझे इस उदाहरण में बेहतर लगता है।
आई विल इट माय हैट

12
इस दृष्टिकोण की अपनी सीमाएं और ऊपरी सीमाएं हैं। आपके प्रत्येक विचार को संसाधित किया जाएगा और वर्तमान स्थिति / प्रॉप्स पर निर्भर करेगा जो मौजूद नहीं हो सकता है। Ex: हम कहते हैं कि आप या तो प्रस्तुत करना चाहते थे: <SearchResults />या <NoResults />। यदि दृश्य स्थिति प्रस्तुत करना चाहिए <NoResults />, <SearchResults />तो संकलित नहीं कर सकता क्योंकि यह उन गुणों पर निर्भर करता है जो अभी तक मौजूद नहीं हैं।
ABCD.ca

3
एक डिफ़ॉल्ट मामले के बारे में क्या?
लामा १२४५

3
@ lama12345 डिफ़ॉल्ट मामले के लिए, ||निम्नानुसार उपयोग करें :{ 'foo': <Foo />, 'bar': <Bar /> }[param] || <Baz />
एरॉन एड्रियन

54

ऐसा इसलिए हो रहा है, क्योंकि switchकथन एक है statement, लेकिन यहाँ जावास्क्रिप्ट एक अभिव्यक्ति की उम्मीद करता है।

हालांकि, एक renderविधि में स्विच स्टेटमेंट का उपयोग करने की अनुशंसा नहीं की जाती है , आप इसे प्राप्त करने के लिए स्व-चालान फ़ंक्शन का उपयोग कर सकते हैं:

render() {
    // Don't forget to return a value in a switch statement
    return (
        <div>
            {(() => {
                switch(...) {}
            })()}
        </div>
    );
}

धन्यवाद कि मैंने इसका इस्तेमाल किया: जैसे: रेंडर () {रिटर्न (<div> {() => स्विच (this.state.type) {केस commons.HARD_SOFT: रिटर्न <हार्डसॉफ्ट params = {this.state.parate} onSubmitHead = {this.onSubmit} />;}}) ()} </ div>);
JhonQO

22

मैंने इसे रेंडर () विधि के अंदर किया:

  render() {
    const project = () => {
      switch(this.projectName) {

        case "one":   return <ComponentA />;
        case "two":   return <ComponentB />;
        case "three": return <ComponentC />;
        case "four":  return <ComponentD />;

        default:      return <h1>No project match</h1>
      }
    }

    return (
      <div>{ project() }</div>
    )
  }

मैंने रेंडर () को साफ रखने की कोशिश की, इसलिए मैंने अपने तर्क को 'कॉन्स्ट' फंक्शन में ऊपर रखा। इस तरह मैं भी बड़े करीने से अपने स्विच मामलों को इंडेंट कर सकता हूं।


@a_m_dev रेंडर विधि के अंदर एक 'कास्ट प्रोजेक्ट' फ़ंक्शन के बजाय, हम इसे एक घटक विधि के रूप में रख सकते हैं, फिर इसे "<div> {this.project ()} </ div>" जैसे रेंडर रिटर्न के अंदर कॉल कर सकते हैं। जब तक आप स्विच का उपयोग नहीं करने के बारे में बात कर रहे हैं, तब तक मैं राज्य का अद्यतन करके क्लासनेम का उपयोग करते हुए / और, या घटकों को दिखाने / छिपाने के बारे में सोच सकता हूं।
विलियम्सि

यह और भी अच्छा हो सकता है, क्योंकि उदाहरण के लिए मैं head()अपने मार्ग घटकों की एक विधि का उपयोग react-helmetअपने दस्तावेज़ के प्रमुख द्वारा डेटा को इंजेक्ट करने के लिए करता हूं
a_m_dev

15

lenkan का जवाब एक महान समाधान है।

<div>
  {{ beep: <div>Beep</div>,
     boop: <div>Boop</div>
  }[greeting]}
</div>

यदि आपको डिफ़ॉल्ट मान चाहिए, तो आप भी कर सकते हैं

<div>
  {{ beep: <div>Beep</div>,
     boop: <div>Boop</div>
  }[greeting] || <div>Hello world</div>}
</div>

वैकल्पिक रूप से, यदि यह आपके लिए अच्छा नहीं है, तो आप कुछ ऐसा कर सकते हैं

<div>
  { 
    rswitch(greeting, {
      beep: <div>Beep</div>,
      boop: <div>Boop</div>,
      default: <div>Hello world</div>
    }) 
  }
</div>

साथ में

function rswitch (param, cases) {
  if (cases[param]) {
    return cases[param]
  } else {
    return cases.default
  }
}

2
{{की 1: <घटक 1 />, ...} [कुंजी] एक अच्छा समाधान नहीं है। आप देखते हैं, चयन होने से पहले, पूरी प्रारंभिक वस्तु का निर्माण किया जाता है - यानी स्विच की प्रत्येक शाखा प्रदान की जाती है - घटक 1, घटक 2, आदि ...
Gleb Varenov

हाँ, लेनकन का उत्तर सही उत्तर होना चाहिए, क्योंकि स्विच को कार्यात्मक घटक में उपयोग नहीं किया जाना चाहिए। डिफ़ॉल्ट मामले में OR जोड़ने के लिए धन्यवाद । और rswitch () के साथ परेशान मत करो, नक्शा समाधान हाजिर है! अंगूठे ऊपर
यूजेनिजस एस।

15

सशर्त ऑपरेटरों का उपयोग करके एक रेंडर ब्लॉक में एक तरह के स्विच का प्रतिनिधित्व करने का एक तरीका :

{(someVar === 1 &&
    <SomeContent/>)
|| (someVar === 2 &&
    <SomeOtherContent />)
|| (this.props.someProp === "something" &&
    <YetSomeOtherContent />)
|| (this.props.someProp === "foo" && this.props.someOtherProp === "bar" &&
    <OtherContentAgain />)
||
    <SomeDefaultContent />
}

यह सुनिश्चित किया जाना चाहिए कि परिस्थितियाँ कड़ाई से बूलियन लौटाती हैं।


2
अच्छा और सुरुचिपूर्ण और रेंडर ब्लॉक में सही उपयोग किया जा सकता है। सर्वश्रेष्ठ उत्तर IMHO
गैविनबेल्सन

2
मैंने देखा कि यह Eslints नियमों का उल्लंघन है eslint.org/docs/rules/no-mixed-operators मिक्सिंग && और ||
फिशफिंगर्स

1
@FishFingers मैंने देखा कि जब मैंने इसे बिल्कुल ऊपर की तरह इस्तेमाल करने की कोशिश की। कोष्ठक में प्रत्येक "मामले" को लपेटकर इसे आसानी से टाला जा सकता है।
च्सेन

13

मैं किसी भी मौजूदा उत्तर का बहुत बड़ा प्रशंसक नहीं हूं, क्योंकि वे या तो बहुत क्रियात्मक हैं, या आपको यह समझने के लिए कोड के चारों ओर कूदने की आवश्यकता है कि क्या हो रहा है।

मैं इसे और अधिक प्रतिक्रिया घटक केंद्रित तरीके से कर रहा हूं, एक बनाकर <Switch/>। इस घटक का काम एक प्रोप लेना है, और केवल उन बच्चों को प्रस्तुत करना है जिनके बच्चे का प्रोप इस से मेल खाता है। इसलिए नीचे दिए गए उदाहरण में मैंने testस्विच पर एक प्रोप बनाया है , और इसकी तुलना valueबच्चों पर एक प्रोप से की है, जो केवल उस मैच का प्रतिपादन कर रहा है।

उदाहरण:

const Switch = props => {
  const { test, children } = props
  // filter out only children with a matching prop
  return children.find(child => {
    return child.props.value === test
  })      
}

const Sample = props => {
  const someTest = true
  return (
    <Switch test={someTest}>
      <div value={false}>Will display if someTest is false</div>
      <div value={true}>Will display if someTest is true</div>
    </Switch>
  )
}

ReactDOM.render(
  <Sample/>,
  document.getElementById("react")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="react"></div>

आप स्विच को जितना चाहें उतना सरल या जटिल बना सकते हैं। बच्चों की अधिक मजबूत जाँच और उनके मूल्य प्रॉप्स का प्रदर्शन करना न भूलें।


3
ठीक वही जो मेरे द्वारा खोजा जा रहा था! यहाँ थोड़ा सुधार है: javascript const Switch = props => { const { test, children } = props; return children.find(child => { return child.props.value === test; }); }; const Case = ({ children, value }) => { return children; // I don't want do add container around my cases ! }; इस तरह से आप लिख सकते हैं:javascript <Switch test={true}> <Case value={true}> <ItAlwaysFeelsRightToBeTrue /> </Case> <Case value={false}> <FalseAlarm /> </Case> </Switch>
lsmod

जबकि यह एक अच्छा समाधान है, कोड में स्पष्टीकरण जोड़कर इसे और भी बेहतर बना दिया जाएगा
पेपी

@papigee थोड़ा और विस्तार के साथ अपडेट किया गया।
मैट वे

@MattWay जबकि शुद्ध JS के लिए यह एक अच्छा विकल्प है, यह एक TS त्रुटि फेंकता है जब लक्ष्य es5 पर सेट हो जाता है क्योंकि संपत्ति ReactNode पर मौजूद नहीं है
Bilal

@ZakriyaBilal कोड अवधारणा के प्रमाण का अधिक है, और स्विच के बारे में कैसे घटक विचार आपके कोड की तरह प्रतिक्रिया करेंगे। कुंजी सिर्फ बच्चों के रंगमंच की सामग्री की तुलना करने का एक तरीका है।
मैट वे

3

कैसा रहेगा:

mySwitchFunction = (param) => {
   switch (param) {
      case 'A':
         return ([
            <div />,
         ]);
      // etc...
   }
}
render() {
    return (
       <div>
          <div>
               // removed for brevity
          </div>

          { this.mySwitchFunction(param) }

          <div>
              // removed for brevity
          </div>
      </div>
   );
}

2

आप ऐसा कुछ कर सकते हैं।

 <div>
          { object.map((item, index) => this.getComponent(item, index)) }
 </div>

getComponent(item, index) {
    switch (item.type) {
      case '1':
        return <Comp1/>
      case '2':
        return <Comp2/>
      case '3':
        return <Comp3 />
    }
  }

2

आपके पास रेंडर में स्विच नहीं हो सकता है। ऑब्जेक्ट-शाब्दिक रूप से एक तत्व को एक्सेस करने वाले प्यूसीडो-स्विच का दृष्टिकोण आदर्श नहीं है क्योंकि यह सभी विचारों को प्रोसेस करने का कारण बनता है और इसके परिणामस्वरूप प्रॉप्स की निर्भरता त्रुटियां हो सकती हैं जो उस स्थिति में मौजूद नहीं हैं।

यहाँ यह करने के लिए एक अच्छा साफ तरीका है कि अग्रिम में प्रस्तुत करने के लिए प्रत्येक दृश्य की आवश्यकता नहीं है:

render () {
  const viewState = this.getViewState();

  return (
    <div>
      {viewState === ViewState.NO_RESULTS && this.renderNoResults()}
      {viewState === ViewState.LIST_RESULTS && this.renderResults()}
      {viewState === ViewState.SUCCESS_DONE && this.renderCompleted()}
    </div>
  )

यदि आपकी स्थिति जिसके लिए दृश्य स्थिति एक साधारण संपत्ति से अधिक पर आधारित है - जैसे प्रति पंक्ति कई शर्तें, तो getViewStateशर्तों को एन्कैप्सुलेट करने के लिए एक एनम और एक फ़ंक्शन इस सशर्त तर्क को अलग करने और अपने रेंडर को साफ करने का एक अच्छा तरीका है।


सरल और साफ तरीका।
अभिलाख सिंह

2

यहाँ घटकों के बीच स्विच करने के लिए एक बटन का उपयोग करके एक पूर्ण कार्य उदाहरण है

आप निम्नलिखित के रूप में एक निर्माता सेट कर सकते हैं

constructor(props)
{
    super(props);
    this.state={
        currentView: ''
    }
}

तो आप निम्नलिखित के रूप में घटकों को प्रस्तुत कर सकते हैं

  render() 
{
    const switchView = () => {

    switch(this.state.currentView) 
    {

      case "settings":   return <h2>settings</h2>;
      case "dashboard":   return <h2>dashboard</h2>;

      default:      return <h2>dashboard</h2>
    }
  }

    return (

       <div>

            <button onClick={(e) => this.setState({currentView: "settings"})}>settings</button>
            <button onClick={(e) => this.setState({currentView: "dashboard"})}>dashboard</button>

            <div className="container">
                { switchView() }
            </div>


        </div>
    );
}

}

जैसा कि आप देख सकते हैं कि मैं राज्यों के बीच स्विच करने के लिए एक बटन का उपयोग कर रहा हूं।


1

मुझे https://stackoverflow.com/a/60313570/770134 में सुझाव पसंद आया , इसलिए मैंने इसे टाइपस्क्रिप्ट के लिए अनुकूलित किया

import React, { FunctionComponent } from 'react'
import { Optional } from "typescript-optional";
const { ofNullable } = Optional

interface SwitchProps {
  test: string
  defaultComponent: JSX.Element
}

export const Switch: FunctionComponent<SwitchProps> = (props) => {
  return ofNullable(props.children)
    .map((children) => {
      return ofNullable((children as JSX.Element[]).find((child) => child.props['value'] === props.test))
        .orElse(props.defaultComponent)
    })
    .orElseThrow(() => new Error('Children are required for a switch component'))
}

const Foo = ({ value = "foo" }) => <div>foo</div>;
const Bar = ({ value = "bar" }) => <div>bar</div>;
const value = "foo";
const SwitchExample = <Switch test={value} defaultComponent={<div />}>
  <Foo />
  <Bar />
</Switch>;

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