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

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

           { switch(...) {} }

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

Now the point is that I have two div elements, one at the top and one at the bottom, that are fixed. In the middle I want to have a switch statement, and according to a value in my state I want to render a different component. So basically, I want the two div elements to be fixed always, and just in the middle to render a different component each time. I'm using this to implement a multi-step payment procedure). Though, as is the code currently it doesn't work, as it gives me an error saying that switch is unexpected. Any ideas how to achieve what I want?


当前回答

这个助手应该可以做到这一点。 使用示例:

{componentSwitch(3, (switcher => switcher
    .case(1, () =>
        <p>It is one</p>
    )
    .case(2, () =>
        <p>It is two</p>
    )
    .default(() =>
        <p>It is something different</p>
    )
))}

助手:

interface SwitchCases<T> {
    case: (value: T, result: () => React.ReactNode) => SwitchCases<T>;
    default: (result: () => React.ReactNode) => SwitchCases<T>;
}

export function componentSwitch<T>(value: T, cases: (cases: SwitchCases<T>) => void) {

    var possibleCases: { value: T, result: () => React.ReactNode }[] = [];
    var defaultResult: (() => React.ReactNode) | null = null;

    var getSwitchCases: () => SwitchCases<T> = () => ({
        case: (value: T, result: () => React.ReactNode) => {
            possibleCases.push({ value: value, result });

            return getSwitchCases();
        },
        default: (result: () => React.ReactNode) => {
            defaultResult = result;

            return getSwitchCases();
        },
    })
    
    // getSwitchCases is recursive and will add all possible cases to the possibleCases array and sets defaultResult.
    cases(getSwitchCases());

    // Check if one of the cases is met
    for(const possibleCase of possibleCases) {
        if (possibleCase.value === value) {
            return possibleCase.result();
        }
    }

    // Check if the default case is defined
    if (defaultResult) {
        // Typescript wrongly assumes that defaultResult is always null.
        var fixedDefaultResult = defaultResult as (() => React.ReactNode);

        return fixedDefaultResult();
    }

    // None of the cases were met and default was not defined.
    return undefined;
}

其他回答

你可以这样做。

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

我在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'函数上面。这样我也可以缩进我的开关盒整齐。

一种在渲染块中使用条件操作符表示一种开关的方法:

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

应该确保条件严格返回布尔值。

import React from 'react';

import ListView from './ListView';
import TableView from './TableView';

function DataView({
    currView,
    data,
    onSelect,
    onChangeStatus,
    viewTodo,
    editTodo,
    deleteTodo,
}) {
    return (
        <div>
            {(function () {
                switch (currView) {
                    case 'table':
                        return (
                            <TableView
                                todos={data}
                                onSelect={onSelect}
                                onChangeStatus={onChangeStatus}
                                viewTodo={viewTodo}
                                editTodo={editTodo}
                                deleteTodo={deleteTodo}
                            />
                        );

                    case 'list':
                        return (
                            <ListView
                                todos={data}
                                onSelect={onSelect}
                                onChangeStatus={onChangeStatus}
                                viewTodo={viewTodo}
                                editTodo={editTodo}
                                deleteTodo={deleteTodo}
                            />
                        );

                    default:
                        break;
                }
            })()}
        </div>
    );
}

export default DataView;

这是因为switch语句是一个语句,但这里javascript需要一个表达式。

虽然,不建议在呈现方法中使用switch语句,但你可以使用自调用函数来实现这一点:

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