Material-ui: [withStyles] Fügen Sie die Möglichkeit hinzu, die Requisiten der Komponente aus dem Stilobjekt zu erhalten

Erstellt am 2. Aug. 2017  ·  39Kommentare  ·  Quelle: mui-org/material-ui

Beschreibung

Wenn Sie createStyleSheet , gibt es keine Möglichkeit (zumindest die mir bekannt ist), auf die Requisiten der Komponente zuzugreifen. Ich denke, dies ist wichtig, da manchmal Größen, URL-Bilder und andere Stile als Requisiten an die Komponente übergeben werden sollen.

Heute ist die einzige Lösung dafür, diese Dinge in Inline-Stile zu unterteilen, aber soweit ich weiß, verwendet material-ui v1 jss und react-jss , und diese beiden bieten Ihnen bereits die Möglichkeit Zugriff auf die Requisiten über Funktionen, die die Requisiten empfangen und dann den gewünschten Stil zurückgeben, wie folgt:

const styles = {
  button: {
    background: props => props.color
  },
  root: {
    backgroundImage: props => `url(${props.backgroundImage})`
  }
}

// Reference: https://github.com/cssinjs/react-jss#example

Was halten Sie davon, so etwas auch auf material-ui zu implementieren?

enhancement important

Hilfreichster Kommentar

Ich füge dieses Problem im

capture d ecran 2018-07-29 a 13 12 03

Alle 39 Kommentare

React-jss implementiert diese Funktion. Sie können es immer über unserer Styling-Lösung verwenden. Die eigentliche Motivation für die Implementierung dieses Features hier sollte eine einfachere/bessere interne Implementierung der Komponenten sein.

response-jss injectStyles() tut dies auch, aber es scheint, dass es besser wäre, Requisiten zu StyleRuleCallback hinzuzufügen.

const styles = (props, theme) => ({})
Auf diese Weise sind Sie nicht nur auf Werte beschränkt, die von Requisiten abhängen.

Das Feedback von color anstelle des vordefinierten bereitzustellen. Die Auswirkung auf die CSS-Größe ist unklar, aber es würde das Überschreiben der Komponentenfarbe noch einfacher machen. Dies ist etwas zu untersuchen. Sobald die Browserunterstützung für CSS-Variablen hoch genug ist (in 2 Jahren?), können wir uns darauf verlassen.

@oliviertassinari würde die CSS-Größe in einigen Fällen nicht tatsächlich abnehmen?
Wie ich es verstehe, definieren wir derzeit alle Klassen für ...Primary und ...Accent - würde diese Änderung nicht bedeuten, dass wir nur Klassen für ...Colorized pflegen müssten? Oder machen Sie sich Sorgen um das generierte CSS?

So oder so denke ich, dass dies dx enorm verbessern würde, da wir im Grunde komplexe Klassen wie https://github.com/callemall/material-ui/blob/v1-beta/src/Button/Button.js#L11 neu implementieren müssen, wenn wir möchten Nicht-Palette-Farben verwenden.

Würde die CSS-Größe in einigen Fällen nicht tatsächlich abnehmen?

@sakulstra Schwer zu sagen. Es wird von der Umsetzung abhängen. Vielleicht :).

Aus Sicht der TypeScript-Typisierung wäre es schön, wenn auf _both_ props und theme innerhalb einer Stilspezifikation props diese Weise zugegriffen werden könnte:

const styles = {
  button: {
    background: ({ theme }) => theme.palette.primary[200]
  },
  root: {
    backgroundImage: ({ props }) => `url(${props.backgroundImage})`
  }
};

Der Grund dafür ist, dass TypeScript häufig nicht den richtigen Typ für withStyles wenn ihm ein Funktionsobjekt übergeben wird, sodass Sie zusätzliche Typannotationen bereitstellen müssen, damit es funktioniert, z

withStyles<'button' | 'root'>(theme => ...)

Wenn auch Requisiten übergeben werden, wird dies zu

withStyles<'button' | 'root', Props>((theme, props) => ...)

Wie ist der aktuelle Stand dazu? Es wäre wirklich schön, diese Funktion zu haben

@lucasmafra Ich habe diese Funktion zum Meilenstein nach der Veröffentlichung nach v1 hinzugefügt. Je früher wir v1 veröffentlichen können, desto besser.

Diese Funktionalität ist der Schlüssel zum Schreiben ausdrucksstarker Stilregeln, die Requisiten, Medienabfragen und interaktive Zustände kombinieren. Sie können diese Funktionalität nicht durch Inline-Stile ersetzen. Leider ist withStyles in keinem meiner Projekte verwendbar, bis dies hinzugefügt wird.

Sie können jederzeit ein benutzerdefiniertes Design einrichten und diese Konvention verwenden: Uns gefällt, wie gestylte Komponenten Ihnen sofort Zugriff auf das props.theme geben, indem Sie ThemeProvider in MuiThemeProvider verschachteln, wenn beide theme={theme} aufgerufen werden. Es erweitert das Standardthema, das mui verfügbar macht

//inline with HOC Method
 h1 style= {{ 'color: this.props.theme.palette.primary[500]' }}

//styled components ( no method necessary )
const Heading = styled.h1`
  color: ${p => p.theme.palette.primary['500']};
`

Ich musste nur Funktionswerte verwenden, also habe ich die injectSheet() Funktion von response-jss verwendet. Ich bin es gewohnt, die withStyles() Funktion von Mui zu verwenden. Gibt es also einen Nachteil, wenn ich injectSheet anstelle von withStyles verwende?

@damien-monni Sie erhalten keinen Zugriff auf Ihr MUI-Theme.

Hallo zusammen, wollte nur meine Version der komponentenähnlichen API im Material-UI-

  • props und theme hochgezogen, um die Funktion zu stylen.
  • Übergeben von benutzerdefinierten props an umschlossene Komponente
  • Weiterleitung von Refs über React.forwardRef
    (BEARBEITEN: Refs funktionieren derzeit nur für HTML-Tags, nicht für die meisten grundlegenden Material-UI-Komponenten, dies erfordert interne Unterstützung. Könnte bei einer PR funktionieren, wenn ich Zeit habe, würde erfordern, function oder object akzeptieren

Verwandte Probleme: #10825, #7633

styled.js

import React, { Component } from 'react';
import classNames from 'classnames';
import PropTypes from 'prop-types';
import { withStyles } from 'material-ui/styles';

function styled(WrappedComponent, customProps) {
  return (style, options) => {
    class StyledComponent extends Component {
      render() {
        let {
          forwardRef,
          classes,
          className,
          ...passThroughProps
        } = this.props;
        return (
          <WrappedComponent
            ref={forwardRef}
            className={classNames(classes.root, className)}
            {...passThroughProps}
            {...customProps}
          />
        );
      }
    }

    StyledComponent.propTypes = {
      classes: PropTypes.object.isRequired,
      className: PropTypes.string,
    };

    let hoistedProps = {};

    const styles =
      typeof style === 'function'
        ? theme => {
            return { root: style({ ...theme, theme, props: hoistedProps }) };
          }
        : { root: style };

    const WithRef = withStyles(styles, options)(StyledComponent);

    return React.forwardRef((props, ref) => {
      hoistedProps = props;
      return <WithRef {...props} forwardRef={ref} />;
    });
  };
}

export default styled;

Anwendungsbeispiel

const MobileNav = styled('nav')(({ theme, props }) => ({
  '&.pos-fixed': {
    top: 0,
    position: props.fixed ? 'fixed' : 'absolute',
    zIndex: 99,
    animation: 'fadeInDown 0.3s ease-out forwards',
    backgroundColor: theme.palette.common.white,
  },
}));

Mit benutzerdefinierten Requisiten

const StyledButton = styled(Button, { component: Link })(
  ({ theme, props }) => ({
    color: props.disabled ? 'gray' : 'blue',
    [theme.breakpoints.down('sm')]: {
      color: 'red',
    },
  })
);

@oliviertassinari Um dieses Problem zu lösen, verwende ich die folgende Lösung:

    componentWillMount() {
        const {color} = this.props;
        jss.setup(jssPreset());
        const stylesheet = jss.createStyleSheet({
            underline: {
              "&:after": {
                backgroundColor: `${color} !important`
              }
            }
        }).attach();
        this.underlineClass = stylesheet.classes.underline;
    }

Es funktioniert großartig, aber gibt es einige potenzielle Probleme, die ich nicht sehe? Ich mag es nicht, dass ich zum Beispiel jss.setup zweimal aufrufen muss 😅. Ich bin mir nicht sicher, ob ich den Lebenszyklus von jss verstehe. Ich war überrascht, dass ich hier setup() aufrufen musste.

Es funktioniert großartig, aber gibt es einige potenzielle Probleme, die ich nicht sehe?

@wcandillon Einige potenzielle

Ich habe diese Bibliothek entwickelt, um Requisiten mit Stil zu haben:

https://github.com/JacquesBonet/jss-material-ui

Erfolgreich in einem Projekt getestet.

Zuerst verwende ich die Danielmahon-Lösung, bekomme aber ein Stilvererbungsproblem.

@oliviertassinari Haben wir

@HunderlineK Some alternatives: https://material-ui.com/customization/overrides/#2-dynamic-variation-for-a-one-time-situation.

@danielmahon Ihr Ansatz ist genau das, wonach ich gerade suche, um mein Problem zu lösen, obwohl die "Styled Component" nicht neu gerendert wird, wenn sie neue Requisiten erhält. Hast du noch was probiert?

Ich werde mir etwas anderes einfallen lassen und wenn mir etwas einfällt, lasse ich es dich wissen

💰 Daran hängt gerade ein Kopfgeld von 50 $ :)

https://www.bountysource.com/issues/47838203-withstyles-add-the-ability-to-get-the-component-s-props-from-within-the-style-object

Wie @lewisdiamond sagte, const styles = (props, theme) => ({}) wäre wirklich ordentlich.

Oder const styles = (theme, props) => ({}) , um vielleicht nicht zu brechen.

Ich füge dieses Problem im

capture d ecran 2018-07-29 a 13 12 03

@oliviertassinari dies hat wahrscheinlich erhebliche Auswirkungen auf die Eingabe von withStyles , lass es mich wissen, wenn ich dabei helfen kann

@pelotom Danke, ich lasse es dich wissen. Ich hoffe, ich kann diesen Monat anfangen, mich mit dem Thema zu befassen.

Gibt es diesbezüglich Arbeiten? Es ist ein wichtiges Feature IMO, vielleicht kann ich dabei helfen.

EDIT: Ich habe angefangen, daran zu arbeiten. Es ist gelungen, Requisiten an die styles Funktion zu übergeben, die withStyles akzeptiert. Das einzige Problem ist, dass Stile nicht aktualisiert werden, wenn sich Requisiten ändern. Werde eine PR erstellen, wenn das gelöst ist.

Hallo, ich bin gerade auf einen Anwendungsfall gestoßen, bei dem ich dies benötigte, um die Farben der Avatar-Komponente anzupassen, und es gibt keine andere Möglichkeit, den Stil für alle Varianten der Komponente anders als diese zu steuern.

const styles = theme => ({
  chip:{
  },
  separator: {
    marginRight: theme.spacing.unit,
  },
  fright: {
    float: 'right',
  },
  fleft: {
    float: 'left',
  },
  outlinedPrimary:{
    color: props =>  stringToColor( props.username),
    border: props => `1px solid ${fade(stringToColor(props.username), 0.5)}`,
    '$clickable&:hover, $clickable&:focus, $deletable&:focus': props => ({
      backgroundColor: fade(stringToColor(props.username), theme.palette.action.hoverOpacity),
      border: `1px solid ${stringToColor(props.username)}`,
      }),
  },
  outlined: {
    backgroundColor: 'transparent',
    border: props => `1px solid ${
      theme.palette.type === 'light' ? stringToColor(props.username) : fade(stringToColor(props.username))
    }`,
    '$clickable&:hover, $clickable&:focus, $deletable&:focus': props => ({
      backgroundColor: fade(stringToColor(props.username), theme.palette.action.hoverOpacity),
      }),
    },
});

Sie können meine Lösung Japrogramer überprüfen: https://github.com/JacquesBonet/jss-material-ui

danke, ich werde es mir anschauen.

Ich brauchte dieses Feature heute früher, also habe ich ein HOC geschrieben. withStyles macht selbst etwas Caching, daher kann ich nicht wirklich sagen, wie sehr sich das auswirkt, aber ich werde mir die Caching-Implementierung von withStyles in meiner Freizeit ansehen, für jetzt alle, die nach einem Schneller Weg, um Requisiten und Themen zu erhalten, um dort gut zu spielen

Warnung

Diese Komponente führt eine vollständige Neumontage durch, wenn sich die Requisiten etwas ändern, was mit der Änderung der Indexnummer der Stylesheet-Klasse oder etwas im withStyles-HOC zu tun hat

import React from 'react';
import { withStyles } from '@material-ui/core/styles';

const { createElement, forwardRef } = React

const withPropsStyles = ( style ) => {

    const withPropsStyles = ( component ) => {

        return forwardRef( (props, ref) => {

            const proxy = (theme) => style(props, theme)

            const hoc = withStyles(proxy)(component)

            return props.children ? 
                createElement(hoc, { ...props, ref}, props.children) :
                createElement(hoc, {...props, ref}) 
        }) 
    }

    return withPropsStyles
}

export default withPropsStyles

Anwendungsbeispiel

const styles = (props, theme) => ({
    root:{
        backgroundColor: props.light ? theme.palette.primary.light : theme.palette.primary.main 
    },
})

const SomeComponent = ({classes}) => <div className={classes.root}/>

export default withPropsStyles(styles)(SomeComponent)

Fazit

Einfach und funktioniert (aber auch die vollen Remount-Kosten)

Können wir mit dieser Änderung die Verwendung von Inline-Stilen aus der Bibliothek zugunsten von 100 % JSS entfernen? Meine App funktioniert nicht mit Inline-Stilen und als ich den Ripple-Effekt durch JSS ersetzen wollte, wurde mir klar, dass ich diese Funktion brauche. Vielleicht ein kleiner Performance-Hit, scheint aber sauberer zu sein.

@koshea lässt den Inline-Stil withStyles als Dekorateur oder wie im Beispiel funktionieren.

Ich wollte auch erwähnen, dass die Verwendung von Inline-Stilen keine strenge Inhaltssicherheitsrichtlinie ermöglicht.
Es erfordert das Hinzufügen des unsafe-inline Flags zu den Style-Direktiven, was nicht sicher ist.

Dynamische Stile mit Unterstützung für Requisiten sollten dieses Problem lösen

Hallo Leute, sorry, dass ich mich in die Diskussion "einfach so" einklinken muss. Ich habe vor kurzem angefangen, Mui (mit Typescript) zu verwenden, und obwohl ich es für eine äußerst leistungsstarke Bibliothek halte, hat sie sicherlich ihre Komplexität.

Ich habe in einigen Kommentaren oben bemerkt, dass es eine Diskussion darüber gibt, ob diese Funktion (props, theme) => {} oder (theme, props) => {} . Ich möchte in seinem Kommentar unterstreichen , was Erstellen von props und theme gesagt hat. Wenn wir das so machen, wird es uns wahrscheinlich leichter fallen, die Stildefinitionen zu überarbeiten, sobald diese Änderung eintrifft (auf die ich mich wirklich freue). Prost 🙂

Vielen Dank an alle für die Geduld! Dieses Problem wird in #13503 behandelt. Dies ist eine Voraussetzung für die Komponentenhelfer, die wir implementieren möchten. Wir haben auch begonnen, mit der Hook-API zu experimentieren: https://twitter.com/olivtassinari/status/1058805751404261376.

Hat es das in 4.0 geschafft? Es sieht so aus, als hätte der makeStyles Callback keinen props Parameter.

@city41 const classes = useStyles(props);

Ich verstehe. So sieht es aus

const useStyles = makeStyles(theme => {
    return {
        foo: {
            color: theme.props.danger ? '#ff0000' : '#00ff00'
        }
    };
});

function MyComponent(props) {
    const classes = useStyles(props);

    return <div className={classes.foo}>...</div>;
}

Ich sehe dies nicht im Abschnitt Stile-API auf der Website dokumentiert. Mal sehen, ob ich eine PR schicken kann.

@city41 Es gibt einen Beginn einer Dokumentation in https://material-ui.com/styles/basics/#adapting -based-on-props.

cool, froh zu sehen, dass die docs aktualisiert werden. Für alle anderen, die zu diesem Thema kommen, hier ist, wie ich Thema und Requisiten kombiniert habe, um eine Komponente zu stylen

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

interface ButtonProps {
    destructive: boolean;
}

const useButtonStyles = makeStyles<Theme, ButtonProps>(theme => {
    return {
        root: props => ({
            backgroundColor: props.destructive ? theme.palette.error.main : theme.palette.primary.main
        })
    };
});

export const PrimaryButton: React.FunctionComponent<ButtonProps> = props => {
    const classes = useButtonStyles(props);

    return <Button {...props} className={classes.root} variant="contained" />;
};

Wie kann ich prop in einer Json-Datei mit externen Stilen verwenden?

zum Beispiel ist dies eine externe Datei

const typographyStyle = {
  title2: {
    fontFamily:"Montserrat",
    fontStyle:"normal",
    fontWeight:"800",
    fontSize:"72px",
    lineHeight:"88px",
    letterSpacing:"-0.02em",
    // color:"#304C82"
    color : props => {
      console.log(props,'c1');
      return props.color
    }

  }
};

export default typographyStyle;

Ich importiere diese Datei und verbreite das Objekt

import typographyStyle from "../assets/jss/material-kit-pro-react/views/componentsSections/typographyStyle";


const styles = theme =>  ({
    ...typographyStyle,
    homeSearch:{
        width: '100%',
        '& div':{
            '& input':{
                "color":"#304C82",
                height: 65,
                fontFamily: 'Open Sans',
                fontStyle: 'normal',
                fontWeight: 800,
                fontSize: '48px',
                lineHeight: '65px',
                letterSpacing: '-0.03em',
                '&::placeholder':{
                    fontFamily: 'Open Sans',
                    fontStyle: 'normal',
                    fontWeight: 800,
                    fontSize: '48px',
                    lineHeight: '65px',
                    letterSpacing: '-0.03em',
                    color: '#EAEAEA'
                }
            }
        }
    },

  });

Jetzt bekomme ich bei der Farbfunktion props = {} .

kann mir diesbezüglich jemand helfen?

AKTUALISIEREN:

Es scheint, als ob ich etwas falsch mache, weil ich sogar in meiner Hauptdatei "styles.js" ein leeres Objekt erhalte

    homeSearch: props => {
        console.log(props);
        return {
        width: '100%',
        border:  `1px solid ${props.color}`
        ,
        '& div':{
            '& input':{
                "color":"#304C82",
                height: 65,
                fontFamily: 'Open Sans',
                fontStyle: 'normal',
                fontWeight: 800,
                fontSize: '48px',
                lineHeight: '65px',
                letterSpacing: '-0.03em',
                '&::placeholder':{
                    fontFamily: 'Open Sans',
                    fontStyle: 'normal',
                    fontWeight: 800,
                    fontSize: '48px',
                    lineHeight: '65px',
                    letterSpacing: '-0.03em',
                    color: '#EAEAEA'
                }
            }
        }
    }
},
War diese Seite hilfreich?
0 / 5 - 0 Bewertungen

Verwandte Themen

ericraffin picture ericraffin  ·  3Kommentare

reflog picture reflog  ·  3Kommentare

FranBran picture FranBran  ·  3Kommentare

finaiized picture finaiized  ·  3Kommentare

sys13 picture sys13  ·  3Kommentare