12

How can I pass post.mainImage to backgroundImage style.

Here is my code;

import React from 'react';
import { Post } from '../interfaces';
import { makeStyles, createStyles, Theme } from '@material-ui/core/styles';
import Container from '@material-ui/core/Container';

type Props = {
  post: Post;
}

const useStyles = makeStyles<Theme, Props>((theme: Theme) =>
  createStyles({
    root: {
      maxWidth: '100%',
      backgroundImage: ({ post }) => post.mainImage
    },
    date: {
      margin: theme.spacing(1),
      marginLeft: theme.spacing(2)
    },
    heroimage: {
      maxWidth: '100%',
      height: 'auto',
      objectFit: 'cover'
    }
  })
);

export default function HeroPost({ post }: Props) {
  const classes = useStyles({ post });
  return (
    <Container className={classes.root}>
      <img alt={post.title} src={post.mainImage} className={classes.heroimage} />
    </Container>
  );
}

The code below has passed without a problem from the linter. But still cannot get the backgroundImage value on the front.

1
  • You should create a minimal reproducible example (preferably on codesandbox)
    – hgb123
    Commented Sep 6, 2020 at 1:18

5 Answers 5

37

You can supply type variables to the call to makeStyles (note that the first one must be the theme type and the second the prop type):

type Props = {
  post: Post;
};

const useStyles = makeStyles<Theme, Props>(theme =>
  createStyles({
    root: {
      maxWidth: '100%',
      backgroundImage: ({ post }) => `url("${post.mainImage}")`
    },
    // ...
  })
);

export default function HeroPost({ post }: Props) {
  const classes = useStyles({ post });

  return (
    // ...
  );
}
10
  • I'm aware this hack but as @Yatrix mentioned above, it's possible to pass with JS but couldn't find a solution for TypeScript.
    – thiras
    Commented Sep 6, 2020 at 0:36
  • Modified my answer - this should fix the TS issue. Commented Sep 6, 2020 at 1:18
  • It still doesn't work. I've used breakpoint to examine if post is defined on backgroundImage: ({ post }) => post.mainImage. Unfortunately it's= undefined.
    – thiras
    Commented Sep 6, 2020 at 12:24
  • 1
    CodeSandbox demo Commented Sep 6, 2020 at 14:21
  • 1
    Typescript seems to lose the inferred type when specifying the two first generic types. My way is to declare the styles as a separate const (styles) first and then setting the third generic for makeStyles to keyof typeof styles. Commented Jul 24, 2021 at 17:14
4

Try this: useStyles is a hook which can take a props in parameters and return the method useStyles.

const useStyles = (props: Props) => {
       const {post} = props;
    
       return makeStyles(theme => ({
           root: {
              maxWidth: '100%',
              backgroundImage: post.mainImage
           },
      }))
    } 
3

You need to pass props with its type directly where you want to access it. This Should work fine.

type BgProps = {
  mainImage: string;
}

const useStyles = makeStyles<Theme, Props>((theme: Theme) =>
  createStyles({
    root: {
      maxWidth: '100%',
      backgroundImage: (props: BgProps) => props.mainImage
    },
    date: {
      margin: theme.spacing(1),
      marginLeft: theme.spacing(2)
    }
  })
);
0

You access the props like this,

backgroundImage: props => props.backgroundImageProp

https://material-ui.com/styles/api/#returns-3

1
  • This doesn't work. Must be related with TypeScript.
    – thiras
    Commented Sep 6, 2020 at 0:26
0

Try this using Typescript :

   const useStyles = makeStyles(theme => ({
           root: ({mainImage}: {mainImage: string}) => ({
                 ...
                 backgroundImage: mainImage
           })        
    })
        
    const component: React.FC => {
        const classes = useStyles({mainImage})
         return ...
    }

Not the answer you're looking for? Browse other questions tagged or ask your own question.