0

How to set the style a react.js component when creating it?

Below is some of my code (partially inherited from a stronger developer and then simplified for brevity).

I want to re-use my LogComponent to print several pages of a Log. However, in some cases I want to force a particular width on the returned List, rather than allowing it to flex as it sees fit.

I would prefer to not define a separate LogComponentFixed or to have an if (...) {return (...)} else {return(...)} in my LogComponent.

I have in mind to do something in Log.js like:

<LogComponent heading={"Page 1"}, lines={page_1}, style={styles.list_1} />
<LogComponent heading={"Page 1"}, lines={page_1}, style={styles.list_2} />

And to then, in LogComponent do something like:

<List style={style}> ... </List>

I also tried using something like

<List className={list_1}> ... </List>

But none of the things I've tried works...

Log.js

import React from 'react'
import Typography from '@material-ui/core/Typography'
import { withStyles } from '@material-ui/core/styles'
import LogComponent from './LogComponent'

const styles = theme => ({
  title: {
    padding: theme.spacing.unit*1.5,
  },
  list_1: {
  },
  list_2: {
    width: "300px"
  },
  listContainer: {
    flexGrow: 1,
    minHeight: 0,
    overflow: 'auto'
  },
})

const Log = ({classes, log}) => {
  const page_1 = log[0];
  const page_2 = log[1];
  return (
    <div>
      <Typography className={classes.title} color="textSecondary" key={1}>
        Example Log
      </Typography>
      <div className={classes.listContainer} key={2}>
        <LogComponent heading={'Page 1'} lines={page_1} />
        <LogComponent heading={'Page 2'} lines={page_2} />
      </div>
    </div>

export default withStyles(styles)(Log)

LogComponent.js

import React from 'react'
import Typography from '@material-ui/core/Typography'
import { withStyles } from '@material-ui/core/styles'
import { List, ListItem, ListItemText } from '@material-ui/core';

const styles = theme => ({
  title: {
    padding: theme.spacing.unit*1.5,
  },
}

const LogComponent = ({classes, list_class, heading, lines}) => {

    return (
    <div className={classes.root}>
    <Typography className={classes.title} color="textSecondary" key={1}>
            {heading}
            </Typography>
            <div>
            <List dense>
                {[...lines[0]].map(e => 
                <ListItem><ListItemText primary={e} /></ListItem>
                )}
            </List>
            </div>                    
    </div>
    )
}

export default withStyles(styles)(LogComponent)
Murilo Cruz
  • 2,387
  • 1
  • 17
  • 19
levraininjaneer
  • 1,157
  • 2
  • 18
  • 38
  • i can see you are using `withStyles` from `material-ui`. You should add it as tag and in your question description, if it is mandatory for your implementation – Murilo Cruz Jul 25 '18 at 13:43
  • Ok, Thanks: I added it. Not sure how mandatory I would consider it, but since it's in the current code, it may as well be in the tag. – levraininjaneer Jul 25 '18 at 13:45

1 Answers1

1

Here you are sending the styles as a prop to LogComponent, that's why it will not be applied as styles to that component you have created. The style attribute is for HTML tags and in material-ui, you can pass styles to a wrapper component also.

In your case you can get the styles inside your LogComponent as below:

Send styles as a prop as you mentioned in the question

<LogComponent heading={"Page 1"}, lines={page_1}, style={styles.list_1} />

Now, you can access it from props,

                                                   // right below get the style
const LogComponent = ({classes, list_class, heading, lines, style}) => {

return (
<div className={classes.root} style={style}> // Look style attribute added, style(value) is from props
<Typography className={classes.title} color="textSecondary" key={1}>
     {heading}
     </Typography>
     <div>
     <List dense>
          {[...lines[0]].map(e => 
                <ListItem><ListItemText primary={e} /></ListItem>
           )}
      </List>
      </div>                    
    </div>
    )
}
Suman Kundu
  • 1,702
  • 15
  • 22
  • Thanks I tried that, but not quite working yet. In the (non-simplified) real code, the LogComponent contains 2 Lists, of which I want the first to have the fixed width, so I need to apply the style to the `` component, not the `
    ` component as in your example. I've tried that, and I get no errors, but I can see that the style is not being applied...
    – levraininjaneer Jul 25 '18 at 14:28
  • if you pass the required style through props it should work fine no matter where you are applying. Maybe check in the browser if the styles are shown there with an error or not. – Suman Kundu Jul 25 '18 at 16:39
  • In the browser, I click inspect element, but I see no notion of a "width" keyword there. Is that what I should be looking for? – levraininjaneer Jul 26 '18 at 07:32
  • @levraininjaneer go to this [CodeSandbox](https://codesandbox.io/s/4051967j7w) link, I have created an implementation – Suman Kundu Jul 26 '18 at 08:20
  • You are the man! That works. What's different this time is that I'm setting the style explicitly and with double curly brackets in when creating the component, while earlier I tried to pass it a pre-defined style. So I do: ``. I would still be interested to know how I can defined the styles at the top, and then pass it, i.e. something like `` ... could you put that in the sandbox? – levraininjaneer Jul 26 '18 at 08:28
  • @levraininjaneer as long as you are passing object you can create it anywhere and pass it no matter whatever depth inside in your component tree, it's like passing a prop which is an object containing styles. Have a good day though , thanks – Suman Kundu Jul 26 '18 at 08:48
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/176783/discussion-between-suman-kundu-and-levraininjaneer). – Suman Kundu Jul 26 '18 at 08:50