My problem: When i set one of three optional values, then that only value is visible, other default values are gone.
type ComponentProps = {
title: string,
children: JSX.Element,
options: {
iconType?: string,
color?: string,
}
}
const Component = ({ title, children, options = {color: '#D3A82B', iconType: 'alert'}: ComponentProps) => {
return <AnotherComponent color={options.color} iconType={options.iconType}/>
}
Usage:
<Component iconType='danger' />
// default color option is gone
CodePudding user response:
Your "usage" doesn't match the ComponentProps
you've provided. Your COmponentProps
says you're expecting an options
prop with color
and iconType
optional properties, but your usage shows you're expecting color
and iconType
to be props themselves, not within option
....?
If you meant to have options
It only makes sense to provide a default value for options
if options
is optional in your component props type; otherwise, the default won't be used since the caller is required to supply options
.
If you want to supply defaults for the iconType
and color
properties of options
and also for options itself, you need to mark options
optional and then supply defaults for color
and iconType
(perhaps via destructuring), and also provide an overall default for options
(which can be {}
if all options have their own defaults):
type ComponentProps = {
title: string;
children: React.ReactNode;
options?: {
// Added `?` to make `options` optional
iconType?: string;
color?: string;
};
};
const Component = ({
title,
children,
// vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv−−− defaults for `color` and `iconType`
options: { color = "#D3A82B", iconType = "alert" } = {},
}: // ^^−− default for `options` as a whole
ComponentProps) => {
// ...use `color` and `iconType` here...
};
Live example (with TypeScript types commented out):
/*
type ComponentProps = {
title: string;
children: React.ReactNode;
options?: {
iconType?: string;
color?: string;
};
};
*/
const Component = ({
title,
children,
options: { color = "#D3A82B", iconType = "alert" } = {},
}/*: ComponentProps*/) => {
return (
<div>
color = {color}, iconType = {iconType}
</div>
);
};
const Example = () => {
// No options at all
const ex1 = <Component title="ex1">ex1</Component>;
// Just `color`
const ex2 = <Component title="ex2" options={{color: "blue"}}>ex2</Component>;
// Just `iconType`
const ex3 = <Component title="ex3" options={{iconType: "information"}}>ex3</Component>;
// Both
const ex4 = <Component title="ex4" options={{color: "blue", iconType: "information"}}>ex4</Component>;
return (
<div>
{ex1}
{ex2}
{ex3}
{ex4}
</div>
);
};
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<Example />);
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.1.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.1.0/umd/react-dom.development.js"></script>
If you didn't mean to have options
...then `ComponentProps needs to be flattened a bit, and you just supply the defaults directly:
type ComponentProps = {
title: string;
children: React.ReactNode;
// No `options` layer
iconType?: string;
color?: string;
};
const Component = ({
title,
children,
color = "#D3A82B",
iconType = "alert",
}: ComponentProps) => {
// ...use `color` and `iconType` here...
};
Live example (with TypeScript types commented out):
/*
type ComponentProps = {
title: string;
children: React.ReactNode;
iconType?: string;
color?: string;
};
*/
const Component = ({
title,
children,
color = "#D3A82B",
iconType = "alert",
}/*: ComponentProps*/) => {
return (
<div>
color = {color}, iconType = {iconType}
</div>
);
};
const Example = () => {
// No `color` or `iconType`
const ex1 = <Component title="ex1">ex1</Component>;
// Just `color`
const ex2 = <Component title="ex2" color="blue">ex2</Component>;
// Just `iconType`
const ex3 = <Component title="ex3" iconType="information">ex3</Component>;
// Both
const ex4 = <Component title="ex4" color="blue" iconType= "information">ex4</Component>;
return (
<div>
{ex1}
{ex2}
{ex3}
{ex4}
</div>
);
};
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<Example />);
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.1.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.1.0/umd/react-dom.development.js"></script>
CodePudding user response:
I have created object with default options called defaultOptions. By doing that i can pass props passed by user into component, as well as spread default options.
export const TOOLTIP_DEFAULT_OPTIONS: TooltipOptions = { color: '#D3A82B', iconType: 'danger' };
type ComponentProps = {
title: string,
children: JSX.Element,
options?: {
iconType?: string,
color?: string,
}
}
const defaultOptions = {
...TOOLTIP_DEFAULT_OPTIONS,
...options,
};
const Component = ({ title, children, options = TOOLTIP_DEFAULT_OPTIONS : ComponentProps) => {
return <AnotherComponent iconType={options.iconType} {...defaultOptions}/>
}