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


当前回答

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

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

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

      {renderSwitch(param)}

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

其他回答

试试这个,它也更干净:在一个函数中获得渲染的开关,并调用它传递你想要的参数。例如:

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>
  );
}
  const [route, setRoute] = useState(INITIAL_ROUTE)

  return (
    <RouteContext.Provider value={{ route, setRoute }}>
      {(() => {
        switch (route) {
          case Route.Home:
            return <PopupHomePage />
          case Route.App:
            return <PopupAppPage />
          default:
            return null
        }
      })()}
    </RouteContext.Provider>

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

我真的很喜欢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>;

你不能在渲染中有开关。放置访问一个元素的对象文字的伪切换方法并不理想,因为它会导致所有视图都要处理,并且可能导致在该状态下不存在的道具的依赖错误。

这里有一个很好的干净的方法来做到这一点,不需要每个视图提前渲染:

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函数封装条件是分离条件逻辑和清理呈现的好方法。