In business logic, how to kill if Else&Switch case rendering components and ts friendly statements, let’s explore and see if you’ve done this before.

Process multiple render results

Considering that we have three completely different components Foo, Bar, and Baz in our code, in order to fit the complexity of the real situation, our demo components not only render different results, but also input parameter is different.

interface IPropsFoo {
  id: string;
}
const Foo = React.memo((props: IPropsFoo) = > {
  return <h1>{props.id}</h1>
})


interface IPropsBar {
  name: string;
}
const Bar = React.memo((props: IPropsBar) = > {
  return <h1>{props.name}</h1>
})


interface IPropsBaz {
  age: number;
}
const Baz = React.memo((props: IPropsBaz) = > {
  return <h1>{props.age}</h1>
})
Copy the code

When dealing with some radio button groups or switchable Tab components, we usually render different results according to different selected keys. Most of the time, we will write the following code easily with a stroke of the pen.

function Demo1() {
  let initialKey: 1 | 2 | 3 = 1;
  const [key] = React.useState(initialKey);
  const [state] = React.useState({ id: ' '.name: ' '.age: 1 });

  let ui: React.ReactNode = ;
  if (key === 1) {
    ui = <Foo id={state.id} />;
  } else if (key === 2) {
    ui = <Bar name={state.name} />;
  } else if (key === 3) {
    ui = <Baz age={state.age} />;
  }

  return <h1>
    {ui}
  </h1>;
}
Copy the code

Analyze behaviors and create a policy pool

It is obvious that the if else branch increases in positive correlation with the number of key enumerations (10 options spawn 10 if else branches), and the cyclomatic complexity of the function increases easily. This is where the strategy pattern comes in. Render the instance as the output, then it would be easy to write a policy pool to describe the output that different keys should hit.

const compUis = {
    1: <Foo id={state.id} />.2: <Bar name={state.name} />.3: <Baz age={state.age} />};return <h1>
    {compUis[key]}
  </h1>;
Copy the code

More efficient operation efficiency

Perhaps most of the time, we write the code above is thought to have a job, but if we pursue more efficient operation efficiency, should not be all components are instantiated in advance, and then according to the key to specific hit, but just before it hit the instantiation of inert, so we can continue to optimize for

const compUis = {
    1: () = > <Foo id={state.id} />.2: () = > <Bar name={state.name} />.3: () = > <Baz age={state.age} />};return <h1>
    {compUis[key]()}
  </h1>;
Copy the code

react/no-unstable-nested-components

The above code looks perfect. It uses the arrow function to wrap the instance and delay instantiation, but esLint validates it to say react/no-unstable- nested-Components, which tells us that it is not allowed to declare unstable components temporarily inside components. This can cause some inexplicable bugs (usually caused by closures) that specify visible links

is a react. createElement(Some) statement, so we can extract the component’s metadata and describe it clearly.

const compMetas = {
    1: { Comp: Foo, props: { id } },
    2: { Comp: Bar, props: { name } },
    3: { Comp: Baz, props: { age } },
  };
  const meta = compMetas[key];

  return <h1>
    {<meta.Comp {. meta.props} / >}
  </h1>;
Copy the code

Missing type verification

The react/no-unstable-nested-components problem was solved, but the component type verification was completely missing. The props declaration for Foo could be written incorrectly, and ts would not be able to detect the error. Associate the different component Comp types with the props types

const compMetas: {
    1: { Comp: typeof Foo, props: Parameters<typeof Foo>[0]},2: { Comp: typeof Bar, props: Parameters<typeof Bar>[0]},3: { Comp: typeof Baz, props: Parameters<typeof Baz>[0},} = {1: { Comp: Foo, props: { id } },
    2: { Comp: Bar, props: { name } },
    3: { Comp: Baz, props: { age } },
  };
  const meta = compMetas[key];

  return <h1>
    {<meta.Comp {. meta.props} / >}
  </h1>;
Copy the code

More streamlined type derivation

So, ts doesn’t need to make any mistakes in _ _^. We can see that this type is redundant. We can modify it a little bit and make it more concise

type CompMeta<C extends
  (React.NamedExoticComponent<any> &amp; { readonly type: (props: any) = >JSX.Element; > = {})Comp: C, props: Parameters<C>[0]};const compMetas: {
    1: CompMeta<typeof Foo>,
    2: CompMeta<typeof Bar>,
    3: CompMeta<typeof Baz>,
  } = {
    1: { Comp: Foo, props: { id } },
    2: { Comp: Bar, props: { name } },
    3: { Comp: Baz, props: { age } },
  };
  const meta = compMetas[key];
Copy the code

conclusion

Have you learned how to write react component ^_^ in ts with strategy mode

One more thing, if you want to try the vue writing experience, composition API and other fun features in react, welcome to ❤ star concent^_^