Home > Back-end >  How to set defaultProps for object React Typescript
How to set defaultProps for object React Typescript

Time:01-25

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}/>
}
  • Related