UNPKG

@modular-component/with-default-props

Version:

ModularComponent stage for handling default props. Part of the @modular-component/default package.

75 lines (64 loc) 2.59 kB
# @modular-component/with-default-props Provides a `with(defaultProps)` stage allowing to set default value for props. Contrary to the standard React `defaultProps` field, the `with(defaultProps)` stage can also _set new props_ that are not surfaced by the component, and react to passed props (or other previous stages) to dynamically compute a default value. ## Usage ```tsx import { ModularComponent } from '@modular-component/core' import { defaultProps } from '@modular-component/with-default-props' const MyComponent = ModularComponent<{ someFlag?: boolean }>() .with(defaultProps({ someFlag: false, someNewProp: 'hello world' })) .with(render(({ props }) => ( // props is inferred as { someFlag: boolean; someNewProp: string } at this point ))) const MyDynamicProps = ModularComponent<{ role: 'user' | 'owner' | 'admin', canEdit?: boolean, canDelete?: boolean }>() .with(defaultProps(({ props }) => ({ canEdit: ['owner', 'admin'].includes(props.role), canDelete: ['owner'].includes(props.role) })) .with(render(({ props }) => { // props is inferred as { role: 'user' | 'owner' | 'admin'; canEdit: boolean; canDelete: boolean } // canEdit defaults to true if the role is not "user", false otherwise // canDelete defaults to true if the role is "admin", false otherwise // canEdit and canDelete can still be controlled by explicitely setting the property }))) ``` ## Implementation `with(defaultProps)` runs a custom stage hook to shallowly merge the default props to the received component props. Accepted values are restricted to a partial map of the original props to only accept correct types for defined props. The value can also be a function of the current args. ```tsx import { ModularStage } from '@modular-component/core' type Merge<Props, DefaultProps extends Partial<Props>> = { [key in keyof Props | keyof DefaultProps]-?: key extends keyof Props ? key extends keyof DefaultProps ? NonNullable<Props[key]> : Props[key] : DefaultProps[key] } export function defaultProps< Args extends { props: {} }, Props extends Args extends { props: infer U } ? U : {}, DefaultProps extends Partial<Props>, >( defaultProps: DefaultProps | ((args: Args) => DefaultProps), ): ModularStage<'props', (args: Args) => Merge<Props, DefaultProps>> { return { field: 'props', useStage: (args: Args) => ({ ...(typeof defaultProps === 'function' ? defaultProps(args) : defaultProps), ...args.props, } as Merge<Props, DefaultProps>), } } ```