-
-
Notifications
You must be signed in to change notification settings - Fork 32.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Can withStyles pass props to styles object? #8726
Comments
We should probably be able to address the issue by making Material-UI using the same context key as react-jss: https://github.com/cssinjs/theming/blob/master/src/channel.js#L1. |
I have a PR ready with a react-jss interoperability example. I will add that into the docs. cc @kof |
@oliviertassinari does the resolution of this mean that it should be possible now to get access to the props within the styles definition? It's not clear to me how... |
@pelotom no, withStyles doesn't have access to the properties. But given how much people are asking for this feature. It's something I can prioritize, after the bug fixes. You can use the injectSheet HOC, but it's open the door to multiple issues: memory leak, hot reloading broken, no |
@oliviertassinari It's very reassuring to hear that you'll consider prioritizing this! This would make it much easier to customize components. For example, I'd like to have a checkbox with a configurable size (i.e. width & height in pixels): <CustomCheckbox size={16} /> If we could access const styles = {
root: {
width: props => props.size,
height: props => props.size
}
} or const styles = props => ({
root: {
width: props.size,
height: props.size
}
}) and then: const CustomCheckbox = ({size, classes}) => <Checkbox className={classes.root} />;
export default withStyles(styles)(CustomCheckbox); For now, do you have any recommendations about how we should approach these types of use cases? Or do you have any estimates of when you might be able to add support for accessing props when using withStyles? |
@nmchaves You use case seems to fall perfectly for the inline-style approach, you can find a bit about it in the documentation. FAQ |
Thanks @oliviertassinari ! I was hoping I could accomplish this using |
it would be nice to be able to pass a prop (image src) to the style for a backgroundImage |
I'd wrap const withStylesProps = styles =>
Component =>
props => {
console.log(props);
const Comp = withStyles(styles(props))(Component);
// return <div>lol</div>;
return <Comp {...props} />;
};
const styles = props => ({
foo: {
height: `${props.y || 50}px`,
}
});
export default withStylesProps(styles)(
props => (
<div className={props.classes.foo} style={{ ...props.style, background: 'yellow' }}>
<h1>Hello!</h1>
</div>
)
); demo: https://codesandbox.io/s/k2y01rj3w7 (I'm surprised ^ works without any |
@caub Thanks for sharing! |
@oliviertassinari there's this https://github.com/cssinjs/react-jss/blob/master/readme.md#dynamic-values in react-jss, I wonder why it couldn't be used in material-ui? Also I understand your point where you say the inline |
I am facing the same issue can some one help me out const drawerWidth = 240; const styles = theme => ({ export class ResponsiveDrawer extends React.Component { handleDrawerToggle = () => { render() {
} ResponsiveDrawer.propTypes = { export default withStyles(styles)(ResponsiveDrawer); |
@oliviertassinari injected CSS will grow +- same way html would grow with inline styles. Static styles are rendered in separate sheets and reused across all component instances. |
I did like this, though with stateless component it will re-render the
We can use full pure component to avoid updating
|
@up209d It works, but it's quite painful, I'll try to modify @SrikanthChebrolu could you move your message to a different issue, since it's not in-topic? |
Just curious what the status is on this? I've been reading through this issue, the JSS docs, material-ui docs, and yet to find a solution for Mui+Jss+TypeScript that doesn't require me to use inline styles. Putting a few inline styles is sometimes unavoidable, but in my case there are multiple styles that have many different states, all relying on theme and props together 😞 |
@chazsolo Hey Chaz, you actually can use
|
@chazsolo I think you want to follow this issue cssinjs/jss#682 |
@up209d
My theme looks like: import { ITheme } from '...';
export default (theme: ITheme) => ({
arc: {
// ...
strokeWidth: (props: any): number | string => {
// this logs the correct data I'm expecting
console.log(props.data[0].properties.name)
return 1.5
}
},
arcMovement: {
// ...
},
}) The interesting this is, when I use the
Update I was able to get this working, but as noted in the comment above, I had to strip out all references to |
@chazsolo Hey Chaz, I am not sure but is that you want to access to |
@iamthuypham your solution has the drawback of creating a new All of that is supported by Also, I think @jdolinski1 's problem is that your code does not propagate |
@iamthuypham I think it is not recommended to do that, as I used to do like that in the past, and you might experience the poor performance as long as the app growth very soon. Creating a new instance of |
how to use plugins such as jss-nested with injectSheet?. with injectSheet i can't get '&:hover' statements work. |
@koutsenko Here is an example: import React from "react";
import { makeStyles } from "@material-ui/styles";
import Button from "@material-ui/core/Button";
const useStyles = makeStyles({
root: {
background: props => props.color,
"&:hover": {
background: props => props.hover
},
border: 0,
borderRadius: 3,
color: "white",
height: 48,
padding: "0 30px"
}
});
export default function Hook() {
const classes = useStyles({
color: "red",
hover: "blue"
});
return <Button className={classes.root}>Hook</Button>;
} https://codesandbox.io/s/pw32vw2j3m I hope it helps. Wow, it's amazing the progress we have made in ~1 year 😍. |
now how do you typescript that? |
@stunaz Good question. I don't know. I haven't looked into it. @eps1lon has done the TypeScript definition of the module. You can use it as a starting point. |
Thanks @oliviertassinari , with "react@next" it works now. |
@koutsenko If you couldn't make |
Can you also set the entire styles object for a given selector with props? To where you can conditionally apply a property? For instance, like this
So that, if the prop does not exist, then it uses the previous fill value, rather than something else that I have to set it to? For instance, there are other rules that would normally apply to fill, but I only want to set this new fill property if the Thanks! |
@Guardiannw For some reason your variant doesn't work. Maybe @kof could raise our light on why 💡. You can do one of the following: // 🏆
const useStyles = makeStyles({
root: {
"& > span": {
backgroundColor: props => props.color || null,
}
}
});
// or
const useStyles = makeStyles({
root: props => ({
"& > span": {
backgroundColor: props.color || null
}
})
}); |
@oliviertassinari I am having a hard time getting your second option to work with the |
@Guardiannw It's working with any of the APIs of |
@oliviertassinari looks like a valid syntax, fn values were added in v10, so either v9 was used or I need a codesandbox reproduction |
Ok, that's what I tried it with. Might have to try again. |
@oliviertassinari I have a question about the use of @materia-ui/styles, is It available and to use in a production environment?, in the documentation indicates that it doesn't work with the stable version, I'm using the "3.9.1", the example https://github.com/mui-org/material-ui/issues/8726#issuecomment-452047345 that you present it has a powerful and useful feature that I need. In these issues, I saw many comments from a different perspective and also I like the solution https://github.com/mui-org/material-ui/issues/8726#issuecomment-363546636 of @caub, but your comment about his solution is good. |
@contrerasjf0 What I hope is that people use those versions either in hobby projects or use it on a separate branch that is not deployed to production but still tested just like the production branch. I do appreciate everyone that uses those alpha versions and gives us feedback for them. |
@up209d yes, your solution work, but with Also, JssProvider isn't necessary. |
// at value level:
styles = { name: { cssprop: props => value }
styles = theme => ({ name: { cssprop: props => value })
// at class name level
styles = { name: props => ({ cssprop: value }) }
styles = theme => ({ name: props => ({ cssprop: value }) }) You can't access |
I found a way
The exported component can now be used like this:
|
@andreasonny83 Avoid this pattern. We are providing a native API in v4. |
@oliviertassinari thanks for the update. Is that pattern already available? Any documentation available? |
One last question @oliviertassinari . Can I use I cannot find documentation for that. What I'm trying to do is this:
|
Use either one or the other, in your example just remove const styles = { message: {boxSizing: 'content-box', background: props => props.bg} };
export const ComponentWithStyles = withStyles(styles)(MyComponent); |
Gday folks thought id share my current solution with reference to the above discussion, hopefully it helps someone or someone could offer better advice on my current solution. For my signin page id like a random background image but id still like to maintain the power of the material ui api. The AuthPage is just the parent presentation layer that takes the individual auth components (signin, locked, forgotten-password, password-reset, etc) as children. Can confirm with each page refresh a new background loads aswell as a nice strongly typed props within AuthPageContainer prop // AuthPage.styles.tsx import { Container } from "@material-ui/core";
import { ContainerProps } from "@material-ui/core/Container";
import { withStyles } from "@material-ui/core/styles";
import React from "react";
interface IAuthContainerProps extends ContainerProps {
background: string;
}
export const AuthContainer = withStyles({
root: props => ({
alignItems: "center",
backgroundImage: `url(${props.background})`,
backgroundPosition: "50% 50%",
backgroundRepeat: "no-repeat",
backgroundSize: "cover",
display: "flex",
height: "100vh",
justifyContent: "center",
margin: 0,
padding: 0,
width: "100%"
})
})((props: IAuthContainerProps) => <Container maxWidth={false} {...props} />); // AuthPage.tsx import React from "react";
import forest from "../../assets/backgrounds/forest.jpg";
import sky from "../../assets/backgrounds/sky.jpg";
import uluru from "../../assets/backgrounds/uluru.jpg";
import { AuthContainer } from "./AuthPage.styles";
const AuthPage = ({ children }) => {
const generateBackground = () => {
const backgrounds = [forest, sky, uluru];
const index = Math.floor(Math.random() * backgrounds.length);
return backgrounds[index];
};
return (
<AuthContainer background={generateBackground()}>{children}</AuthContainer>
);
};
export default AuthPage; |
simply do something like this: // styles.js
export default theme => ({
root: props => ({
// some styles
}),
...
});
//container.js
export default withStyles(styles)(MyComponent); |
what about passing also state? |
@luky1984 // Component.js
<Button
className={`
${classes.button}
${this.state.isEnable
? classes.enable
: classes.disable}
`}
/> Or use clsx https://www.npmjs.com/package/clsx instead |
@caub Your solution ruins the jss generated classname order. background should be #0000000 and color: blue |
Currently, I developing a component that requires both props and themes object.
At first, it works great with theme object
But I also need access to props in styles object.
I tried example but it not working.
I end up combine
react-jss
andwithTheme
to do thatIt works but I really miss
The text was updated successfully, but these errors were encountered: