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
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> & { 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^_^