4

I am trying to create a switch HOC for conditional rendering which behaves like a switch statement in ReactTS

<Switch>
    <Case condition={cond1}>
        Hello
    </Case>
    <Case condition={cond2}>
        World
    </Case>
    <Default>
         Hi stranger
    </Default>
</Switch>

If the cond1 is true, render "Hello".
If the cond1 is false but cond2 is true, render "World".
If both conditions are false, render "Hi stranger".

Drew Reese
  • 165,259
  • 14
  • 153
  • 181
Nikhil Goyal
  • 1,945
  • 1
  • 9
  • 17
  • I am not able to figure out how to render that particular child and ignore all the others. I know how to do it via a ternary operator. But not sure how can I have the TSX element similar to the one mentioned in the question. – Nikhil Goyal Mar 13 '21 at 07:20
  • 1
    You will likely need to make use of the [React.Children](https://reactjs.org/docs/react-api.html#reactchildren) utility to access the children of the `Switch` and use the Context API so each `Case` and `Default` component can pass their condition predicate to the `Switch` to be processed and conditionally rendered. I think the tricky bit may be the typing if you are using Typescript. – Drew Reese Mar 13 '21 at 07:28
  • 2
    React Router does similar thing. Maybe you should check react-router's [source code](https://github.com/ReactTraining/react-router/blob/master/packages/react-router/modules/Switch.js). – Ajeet Shah Mar 13 '21 at 07:31
  • 2
    @AjeetShah I was thinking the same exact thing. +1 – Drew Reese Mar 13 '21 at 07:32

1 Answers1

2

I created three files in JS once to test and everything is working fine.

Switch.js

class Switch extends React.Component {
  getComponentToRender() {
    return React.Children.toArray(this.props.children).find(function (child) {
      if (child.type.name === "Case") {
        if (child.props.condition) {
          return true;
        }
      }
      if (child.type.name === "Default") {
        return true;
      }
      return false;
    });
  }

  render() {
    return this.getComponentToRender();
  }
}

export default Switch;

Case.js -> Need to make sure that this component gets condition as boolean.

export default function(props) {
  return props.children;
}

Default.js

export default function(props) {
  return props.children;
}

Using the above files as

<Switch>
        <Case condition={false}>Hello</Case>
        <Case condition={false}>World</Case>
        <Default>Hi</Default>
      </Switch>
Nikhil Goyal
  • 1,945
  • 1
  • 9
  • 17