如何在React组件中使用switch语句?

时间:2017-10-05 18:52:00

标签: reactjs

我有一个React组件,在组件的render方法中我有这样的东西:

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

           { switch(...) {} }

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

现在重点是我有两个div元素,一个在顶部,一个在底部,是固定的。在中间我想要一个switch语句,根据我的状态中的值,我想渲染一个不同的组件。所以基本上,我希望始终修复两个div元素,并且只是在中间每次渲染一个不同的组件。我用这个来实现多步付款程序)。虽然,代码目前它不起作用,因为它给我一个错误,说switch是意外的。任何想法如何实现我想要的东西?

20 个答案:

答案 0 :(得分:64)

试试这个,这也更清晰:在函数中从渲染中取出那个开关,然后调用它传递你想要的参数。例如:

&#13;
&#13;
SELECT BUILDINGNO.BUILDING, AVG(SESSIONPRICE.CONFERENCESESSION)
FROM BUILDING
JOIN CONFERENCESESSION ON BUILDINGNO.BUILDING = BUILDINGNO.CONFERENCESESSION
WHERE BUILDINGNO.BUILDING = SESSIONPRICE.CONFERENCESESSION
GROUP BY BUILDINGNO.BUILDING
Order by AVG(SESSIONPRICE.CONFERENCESESSION) DESC
limit 2;
&#13;
&#13;
&#13;

答案 1 :(得分:25)

发生了这种情况,因为<?php $laborTotals = array(); $totalLaborDollars= 0; $laborTotals[$laborAnalysis['jobcode']]['jobcode'] = $laborAnalysis['jobrole']; $laborTotals[$laborAnalysis['jobcode']]['jobdescription'] = $laborAnalysis['jobdescription']; $laborTotals[$laborAnalysis['jobcode']]['totalsalary'] += $laborAnalysis['totalsalary']; } foreach ($laborTotals as $labor) { $html .= ' <tr>'; $html .= ' <td class="gridData">' . $labor['jobcode'] . '</td>'; $html .= ' <td class="gridData">' . $labor['jobdescription'] . '</td>'; $html .= ' <td class="gridData txtLeft"><b>$</b>' . number_format($labor['totalsalary'], 2, '.', ',') . '</td>'; $totalLaborDollars+=$labor['totalsalary']; } ?> 语句是switch,但这里javascript需要一个表达式。

虽然不建议在statement方法中使用switch语句,但您可以使用自调用函数来实现此目的:

render

答案 2 :(得分:23)

与其他答案相反,我希望在render函数中内联“开关”。这样可以更清楚地知道在该位置可以渲染哪些组件。您可以使用普通的旧javascript对象来实现类似switch的表达式:

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

答案 3 :(得分: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>

您可以根据需要使开关简单或复杂。不要忘记对孩子及其价值道具进行更强大的检查。

答案 4 :(得分:7)

使用条件运算符在渲染块中表示一种开关情况的方法:

{this.props.someVar == 1 &&
    <SomeContent/>
|| this.props.someVar == 2 &&
    <SomeOtherContent />
|| this.props.someOtherVar == 1 &&
    <YetSomeOtherContent />
||
    <SomeDefaultContent />
}

我建议添加一些括号以确保获得预期结果,除非掌握运算符的优先级...

答案 5 :(得分: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>
   );
}

答案 6 :(得分: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>
    );
}

}

如您所见,我正在使用按钮在状态之间进行切换。

答案 7 :(得分:1)

我在render()方法中做到了这一点:

App.xaml

我试图使render()返回保持干净,因此我将逻辑放在上面的'const'函数中。这样,我也可以整齐地缩进我的开关盒。

答案 8 :(得分: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>;

答案 9 :(得分:1)

我将接受的答案转换为箭头功能组件解决方案,看到 James 提供了类似的答案,并且可能会出现错误 not defined。所以这里是解决方案:

  const renderSwitch = (param) => {
    switch (param) {
      case "foo":
        return "bar";
      default:
        return "foo";
    }
  };

  return (
    <div>
      <div></div>

      {renderSwitch(param)}

      <div></div>
    </div>
  );

答案 10 :(得分:0)

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

答案 11 :(得分:0)

您不能在渲染中进行切换。放置访问一个元素的对象文字的伪切换方法不是理想的,因为它会导致处理所有视图,并可能导致该状态下不存在的prop的依赖项错误。

这是一种很好的干净方法,不需要预先渲染每个视图:

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函数来封装条件是一种很好的方式来分隔条件逻辑和清理渲染。

答案 12 :(得分:0)

这是另一种方法。

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

renderStep0() { return 'step 0' }
renderStep1() { return 'step 1' }

答案 13 :(得分:0)

你可以这样做。

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

答案 14 :(得分: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}`}
/>

答案 15 :(得分: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>
  );
}

答案 16 :(得分:0)

React 组件中的 Switch-Case 语句可以如下使用:

<div  id="time-list">
{   
    (() => {
        switch (groupByFilterId) {
            case 0:/*Case 0 */
                return (
                    <div>Case 0</div>
                )
               break;
           case 1: /*Case 1 */
           return ( 
            <div>Case 1</div>
            )
            break;
           case 2:/*Case 2 */
           return ( 
            <div>Case 2</div>
            )
            break;
        }
     })()}

      
       
    
    </div>

答案 17 :(得分:0)

我知道我参加聚会有点晚了,但我认为这个实现可能会有所帮助

您可以使用条件运算符来渲染组件

如果你有以下 switch 语句

switch(value) {
    case CASE1:
        return <Case1Component/>

    case CASE2:
        return <Case2Component/>

    case CASE3:
        return <Case3Component/>

    default:
        return <DefaultComponent/>
}

你可以把它转换成这样的反应组件

const cases = [CASE0, CASE1, CASE2]
// Reminds me of 'react-router-dom'
return (
    <div>
        {value === cases[0] && <Case0Component/>}
        {value === cases[1] && <Case1Component/>}
        {value === cases[2] && <Case2Component/>}
        {!cases.includes(value) && <DefaultComponent/>}
    </div>
)

答案 18 :(得分:-1)

让它变得简单,只需使用许多 if 语句。

例如:

<Grid>
   {yourVar==="val1"?(<> your code for val1 </>):nul}
   {yourVar==="val2"?(<> your code for val2 </>):nul}
   .... other statments
</Grid>

答案 19 :(得分:-1)

这个答案专门针对@tonyfat 的 this "duplicate" question 问题,关于如何使用条件表达式来处理相同的任务。


在这里避免语句似乎比它的价值更麻烦,但是这个脚本完成了该代码段演示的工作:

// Runs tests
let id = 0, flag = 0;
renderByFlag(id, flag); // jobId out of range

id = 1; // jobId in range
while(++flag < 5){ // active flag ranges from 1 to 4
  renderByFlag(id, flag);
}

// Defines a function that chooses what to render based on two provided values
function renderByFlag(jobId, activeFlag){
  jobId === 1 ? (
      activeFlag === 1
        ? render("A (flag = 1)")
        : activeFlag === 2
          ? render("B (flag = 2)")
          : activeFlag === 3
            ? render("C (flag = 3)")
            : pass(`flag ${activeFlag} out of range`)
  )
  : pass(`jobId ${jobId} out of range`)
}

// Defines logging functions for demo purposes
function render(val){ console.log(`Rendering ${val}`); }
function pass(reason){ console.log(`Doing nothing (${reason})`) }