Is there a way to both destructure a function parameter, and kee

ghz 6months ago ⋅ 77 views

Is there a way to both destructure a function parameter, and keep a named reference to the parameter?

In react stateless functional components we'll commonly write something like this:

export function MyCompoment({
    title, 
    foo, 
    bar
}) {
    return <div> title: {title}, ...</div>
}

Where we're immediately destructuring the props object into its variables.

Now I'm using a Material-UI makeStyles hook, and I'm also using TypeScript, and the way I'm currently using it looks like this.

const useStyles = makeStyles((theme : Theme ) =>({
     root: ({foo} : MyComponentProps) => ({
         content: foo
     })
}); 

interface MyComponentProps  {
    title: string; 
    foo: string; 
    bar: string; 
}
export function MyCompoment({
    title, 
    foo, 
    bar
} : MyComponentProps) {
    const classes = useStyles({
        title,
        foo, 
        bar
    }); 
    return <div> title: {title}, ...</div>
}

And you can see the problem - I have to repeat the props variable names to pass into the classes.

The best way I can think to avoid this, is write it this way:

export function MyCompoment(props: MyComponentProps) {
    const {
       title, 
       foo, 
       bar
    }  = props; 
    const classes = useStyles(props); 
    return <div> title: {title}, ...</div>
}

But that's a little messier than I was wanting.

I was wondering if it's possible to do something like:

export function MyCompoment({
       title, 
       foo, 
       bar
    }  = props : MyComponentProps) {

    const classes = useStyles(props); 
    return <div> title: {title}, ...</div>
}

Pretty picky I know, just wondering.

Answers

In TypeScript with React functional components, especially when using Material-UI's makeStyles hook, you have a couple of options to streamline your component code while avoiding unnecessary repetition of prop names.

Let's explore a couple of approaches:

Approach 1: Destructuring Props and Passing to makeStyles

You can destructure the props immediately in the function arguments and then use them directly in the makeStyles hook:

import React from 'react';
import { makeStyles, Theme } from '@material-ui/core/styles';

interface MyComponentProps {
    title: string;
    foo: string;
    bar: string;
}

const useStyles = makeStyles((theme: Theme) => ({
    root: ({ foo }: MyComponentProps) => ({
        content: foo,
    }),
}));

export function MyComponent({ title, foo, bar }: MyComponentProps) {
    const classes = useStyles({ foo }); // Pass only necessary props
    return <div>title: {title}, ...</div>;
}
  • Explanation:
    • Props Destructuring: Destructure title, foo, and bar directly from MyComponentProps.
    • Passing to makeStyles: Pass only the necessary props (foo in this case) to makeStyles. This avoids passing unnecessary props and keeps the hook concise.

Approach 2: Using Spread Operator with Props

If you prefer to keep your props intact and pass them all to makeStyles, you can use the spread operator (...props) to achieve this:

import React from 'react';
import { makeStyles, Theme } from '@material-ui/core/styles';

interface MyComponentProps {
    title: string;
    foo: string;
    bar: string;
}

const useStyles = makeStyles((theme: Theme) => ({
    root: (props: MyComponentProps) => ({
        content: props.foo,
    }),
}));

export function MyComponent(props: MyComponentProps) {
    const classes = useStyles(props); // Pass all props to useStyles
    return <div>title: {props.title}, ...</div>;
}
  • Explanation:
    • Passing All Props: Use useStyles(props) to pass all props (title, foo, bar) to makeStyles.
    • Accessing Specific Props: Inside makeStyles, access the specific prop (foo in this case) as props.foo.

Conclusion

Both approaches are valid and can be chosen based on personal preference and specific requirements of your application. The second approach keeps your props intact and might be preferable if you need to access multiple props inside makeStyles. The first approach minimizes the props passed to makeStyles, potentially improving performance and reducing unnecessary re-renders.

Choose the approach that fits best with your component structure and readability preferences. Each approach ensures type safety and clarity in your TypeScript codebase.