React 구성 요소 내에서 switch 문을 사용하는 방법은 무엇입니까?


120

React 구성 요소 render가 있고 구성 요소 메서드 내부에 다음과 같은 것이 있습니다.

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

           { switch(...) {} }

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

이제 요점은 두 개의 div요소가 있는데, 하나는 상단에 하나는 하단에 고정되어 있다는 것입니다. 중간에는 switch 문이 있고 내 상태의 값에 따라 다른 구성 요소를 렌더링하고 싶습니다. 그래서 기본적으로 두 div요소는 항상 고정되고 중간에 매번 다른 구성 요소를 렌더링하기를 원합니다 . 나는 이것을 사용하여 다단계 지불 절차를 구현하고 있습니다). 현재 코드 switch가 그렇듯이 예상치 못한 오류가 발생하므로 작동하지 않습니다 . 내가 원하는 것을 달성하는 방법에 대한 아이디어가 있습니까?


1
글쎄, 당신은 return진술 에 모든 논리 또는 심지어 render그 문제에 대한 방법 을 가질 필요가 없습니다 . 각각 <div>을 const로 정의한 다음 switch 앞에 를 사용하여 렌더링해야 할 항목 return을 결정할 <div>수 있습니까?
Jared Goguen

@JaredGoguen하지만 그런 다음 .NET Framework의 div각 경우에 대해 위쪽과 아래쪽에서 여러 번 반복해야 합니다 switch. 아니면 그냥 오해 했어 ..
오타

아니요, 코드를 let middleDiv = ...만든 다음 거기에 하드 코딩 {middleDiv}한 두 개의 JSX 사이에 반환 JSX 를 포함 할 수 있습니다 <div>.
Jared Goguen 2017 년

답변:


218

이것도 시도 해보세요. 함수의 렌더링에서 스위치를 꺼내 원하는 매개 변수를 전달하기 만하면됩니다. 예를 들면 :

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>
  );
}


103

다른 답변과 달리 렌더링 기능에서 "스위치"를 인라인하는 것을 선호합니다. 해당 위치에서 어떤 구성 요소를 렌더링 할 수 있는지 더 명확하게 알 수 있습니다. 일반 오래된 자바 스크립트 객체를 사용하여 스위치와 같은 표현식을 구현할 수 있습니다.

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

1
이것은 꽤 멋지다. POJO 대신 배열을 사용하도록 약간 수정했으며 인덱스를 사용하여 배열을 브래킷으로 묶었습니다.
Nicholas Gentile

1
이것은 Python에서 switch-case를 처리하는 표준 방법입니다. 가독성이 뛰어나이 경우에 더 좋습니다.
I 'll Eat My Hat

16
이 접근 방식에는 한계와 오버 헤드가 있습니다. 각 뷰가 처리되고 존재하지 않을 수있는 현재 상태 / 소품에 따라 달라집니다. 예 : 렌더링을 원한다고 가정 해 보겠습니다 : <SearchResults />또는 <NoResults />. 뷰 상태 렌더링해야하는 경우 <NoResults />, <SearchResults />아직 존재하지 않는 속성에 의존하기 때문에 컴파일하지 않을 수 있습니다.
ABCD.ca 2019

6
기본 케이스는 어떻습니까?
kungfooman

7
@ 기본 케이스 lama12345는, 사용 ||등은 다음과 같습니다{ 'foo': <Foo />, 'bar': <Bar /> }[param] || <Baz />
아론 아드리안

56

그 이유는 switch진술이statement 이지만 여기서 자바 스크립트는 표현식을 기대 합니다.

render메서드 에서 switch 문을 사용하는 것은 권장되지 않지만 자체 호출 함수를 사용하여이를 달성 할 수 있습니다.

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

감사합니다. 다음과 같이 사용했습니다. render () {return (<div> {(() => {switch (this.state.type) {case commons.HARD_SOFT : return <HardSoft params = {this.state.param} onSubmitHead = {this.onSubmit} />;}}) ()} </ div>);
JhonQO

권장되지 않는 이유는 무엇입니까?
bluenote10

그는 어딘가에서 누군가에게 못 생기기 때문에하지 말라고 말하는 것을 읽었을 것입니다. 많은 사람들이 다양한 이유로 switch 문을 좋아하지 않습니다. React 문서에 언급되어 있지 않지만 조건부 렌더링은 React에서 분명히 지원되며 switch 문은 React에 문제를 일으키지 않습니다.
William

22

render () 메서드 내에서 이렇게했습니다.

  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>
    )
  }

render () 반환을 깨끗하게 유지하려고 했으므로 바로 위에 'const'함수에 논리를 넣었습니다. 이렇게하면 스위치 케이스를 깔끔하게 들여 쓸 수도 있습니다.


@a_m_dev render 메서드 내부에 'const project'함수 대신 컴포넌트 메서드로 배치 한 다음 "<div> {this.project ()} </ div>"와 같이 render return 내부에서 호출 할 수 있습니다. 스위치를 전혀 사용하지 않는 것에 대해 이야기하지 않는 한 if / else 사용을 생각하거나 상태를 업데이트하여 className을 사용하여 구성 요소를 표시 / 숨길 수 있습니다.
williamsi

그 수 좋은 더 예를 들어 내가 사용하기 때문에 head()하여 데이터를 삽입하는 내 경로 구성 요소의 방법을 react-helmet내 문서의 머리에
a_m_dev

16

조건 연산자를 사용하여 렌더 블록에서 일종의 스위치 를 표현하는 방법 :

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

조건이 부울을 엄격하게 반환하는지 확인해야합니다.


2
멋지고 우아하며 렌더 블록에서 바로 사용할 수 있습니다. Best answer IMHO
GavinBelson 2010-04-03

2
나는 이것이 EsLints 규칙 eslint.org/docs/rules/no-mixed-operators 혼합 && 및 ||
FishFingers

1
@FishFingers 위와 똑같이 사용하려고 할 때도 그 사실을 알았습니다. 각 "케이스"를 괄호로 묶어 쉽게 피할 수 있습니다.
Ch0sen

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
{{key1 : <Component1 />, ...} [key]는 좋은 솔루션이 아닙니다. 당신은 선택이 일어나기 전에, 전체 초기 개체가 구성되어, 참조 - 즉, 스위치의 모든 지점이 렌더링 - 등 컴포넌트 1, 컴포넌트 2를 ...
에 Gleb Varenov에게

네, 기능적 구성 요소에서 스위치를 사용해서는 안되기 때문에 lenkan의 대답이 정답이어야합니다. 기본 케이스에 OR 을 추가해 주셔서 감사합니다 . 그리고 rswitch ()에 신경 쓰지 마십시오.지도 솔루션이 있습니다! 엄지 손가락
Eugenijus S.

14

나는 너무 장황하거나 무슨 일이 일어나고 있는지 이해하기 위해 코드를 뛰어 넘도록 요구하기 때문에 현재 답변을 좋아하지 않습니다.

나는 <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

@papigee 약간 더 자세하게 업데이트되었습니다.
Matt Way

@MattWay 이것은 순수한 JS에 대한 좋은 옵션이지만 ReactNode에 속성 찾기가 존재하지 않기 때문에 대상이 es5로 설정되면 TS 오류가 발생합니다
Zakriya Bilal

@ZakriyaBilal 코드는 개념 증명에 가깝고 스위치와 같은 아이디어를 구성하여 코드가 어떻게 반응하는지에 대한 것입니다. 핵심은 아이들의 소품을 비교하는 방법을 찾는 것입니다.
Matt Way

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을 캡슐화 하는 열거 형 및 함수는이 조건부 논리를 분리하고 렌더링을 정리하는 좋은 방법입니다.


간단하고 깨끗한 방법.
Abhilekh Singh 19

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 의 제안이 정말 마음 에 들어서 Typescript에 적용했습니다.

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>;

0

나는 어떤 대답에도 절대적으로 만족하지 않았습니다. 그러나 @Matt Way에서 몇 가지 아이디어를 얻었습니다.

내 해결책은 다음과 같습니다.

정의 :

const Switch = props => {
    const { test, children = null } = props;
    return children && children.find(child => child && child.props && child.props.casevalue === test) || null;
}

const Case = ({ casevalue = false, children = null }) => <div casevalue={`${casevalue}`}>{children}</div>;

Case.propTypes = {
    casevalue: PropTypes.string.isRequired,
    children: PropTypes.node.isRequired,
}

const Default = ({ children }) => children || <h1>NO_RESULT</h1>;

const SwitchCase = ({ test, cases = [], defaultValue = null }) => {

    const defaultVal = defaultValue
        && React.cloneElement(defaultValue, { key: 'default-key', casevalue: `${test}` })
        || <Default key='default-key' casevalue={`${test}`} />;

    return (
        <Switch test={`${test}`} >
            {
                cases.map((cas, i) => {
                    const { props = {} } = cas || {};
                    const { casevalue = false, ...rest } = props || {};

                    return <Case key={`case-key-${i}`} casevalue={`${casevalue}`}>{ React.cloneElement(cas, rest)}</Case>
                })
                .concat(defaultVal)
            }
        </Switch>
    );
}

용법:

<SwitchCase
  cases={[
    <div casevalue={`${false}`}>#1</div>,
    <div casevalue={`${true}`}>#2</div>,
    <div casevalue={`${false}`}>#3</div>,
  ]}
  defaultValue={<h1>...nothing to see here</h1>} // You can leave it blank.
  test={`${true}`}
/>

0

function Notification({ text, status }) {
  return (
    <div>
      {(() => {
        switch (status) {
          case 'info':
            return <Info text={text} />;
          case 'warning':
            return <Warning text={text} />;
          case 'error':
            return <Error text={text} />;
          default:
            return null;
        }
      })()}
    </div>
  );
}

-1

이것은 또 다른 접근 방식입니다.

render() {
   return {this[`renderStep${this.state.step}`]()}

renderStep0() { return 'step 0' }
renderStep1() { return 'step 1' }
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.