我有一个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?


当前回答

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

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

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

其他回答

我将接受的答案转换为箭头功能组件解决方案,看到James提供了类似的答案,可以得到未定义的错误。这就是解决方案:

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

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

      {renderSwitch(param)}

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

这个答案专门用来解决@tonyfat提出的“重复”问题,关于如何使用条件表达式来处理相同的任务。


Avoiding statements here seems like more trouble than it's worth, but this script does the job as the snippet demonstrates:

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

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

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

我们可以直接使用useCallback来做到这一点

const renderContent = useCallback(() => { switch (sortState) { “一”: 返回“一”; “两个”: 返回“两个”; “三”: 返回“三”; “四”: 返回“四”; 默认值: 返回“一”; } }, [sortState]);

这将在jsx中使用

<div>排序:{renderContent()}</div>

与其他答案相比,我更倾向于在渲染函数中内联“开关”。它使什么组件可以在那个位置呈现更清楚。你可以使用一个简单的javascript对象来实现一个类似switch的表达式:

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