Material-ui: [withStyles] Tambahkan kemampuan untuk mendapatkan props komponen dari dalam objek style

Dibuat pada 2 Agu 2017  ·  39Komentar  ·  Sumber: mui-org/material-ui

Keterangan

Saat menggunakan createStyleSheet , tidak ada cara (setidaknya yang saya ketahui) untuk mengakses props komponen. Saya pikir ini penting, karena terkadang ingin meneruskan ukuran, gambar url, dan gaya lainnya sebagai alat peraga ke komponen.

Hari ini satu-satunya solusi untuk ini adalah memisahkan hal-hal ini menjadi gaya sebaris, tetapi sejauh yang saya tahu, material-ui v1 menggunakan jss dan react-jss , dan keduanya sudah memberi Anda kemungkinan mengakses alat peraga melalui fungsi yang menerima alat peraga dan kemudian mengembalikan gaya yang diinginkan, seperti itu:

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

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

Apa pendapat Anda tentang menerapkan sesuatu seperti itu pada material-ui juga?

enhancement important

Komentar yang paling membantu

Saya menambahkan masalah ini dalam tonggak sejarah v1.x . Banyak orang yang memintanya. Kami akan segera mendapatkannya.

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

Semua 39 komentar

react-jss mengimplementasikan fitur itu. Anda selalu dapat menggunakannya di atas solusi penataan gaya kami. Motivasi sebenarnya untuk mengimplementasikan fitur itu di sini harus seputar implementasi internal komponen yang lebih sederhana/lebih baik.

react-jss injectStyles() melakukan ini juga, tetapi tampaknya akan lebih baik untuk menambahkan alat peraga ke StyleRuleCallback .

const styles = (props, theme) => ({})
Dengan begitu Anda tidak terbatas hanya pada nilai tergantung pada alat peraga.

Umpan balik color untuk komponen kami, alih-alih yang telah ditentukan sebelumnya. Dampak ukuran CSS tidak jelas tetapi akan membuat penggantian warna komponen menjadi lebih sederhana. Ini adalah sesuatu untuk diselidiki. Kemudian, setelah dukungan browser variabel css cukup tinggi (2 tahun dari sekarang?), kita dapat mengandalkannya.

@olivietassinari bukankah ukuran css benar-benar berkurang dalam beberapa kasus?
Seperti yang saya mengerti, saat ini kami mendefinisikan semua kelas untuk ...Primary dan ...Accent - bukankah perubahan ini berarti, bahwa kami hanya perlu mempertahankan kelas untuk ...Colorized ? Atau apakah Anda khawatir tentang css yang dihasilkan?

Either way, saya pikir ini akan sangat meningkatkan dx karena pada dasarnya kita harus mengimplementasikan kembali kelas kompleks seperti https://github.com/callemall/material-ui/blob/v1-beta/src/Button/Button.js#L11 ketika kita ingin menggunakan warna non palet.

bukankah ukuran css benar-benar berkurang dalam beberapa kasus?

@sakulstra Sulit untuk diceritakan. Itu akan tergantung pada implementasinya. Mungkin :).

Dari perspektif pengetikan TypeScript, akan lebih baik jika _both_ props dan theme dapat diakses dengan cara ini dalam spesifikasi gaya:

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

Alasannya adalah TypeScript sering gagal menyimpulkan tipe yang tepat untuk withStyles ketika dilewatkan objek fungsi, jadi Anda harus memberikan anotasi tipe tambahan untuk membuatnya berfungsi, mis.

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

Jika alat peraga dilewatkan juga, ini akan menjadi

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

Apa status saat ini? Akan sangat menyenangkan memiliki fitur itu

@lucasmafra Saya telah menambahkan fitur ini ke tonggak rilis post v1. Semakin cepat kami dapat merilis v1, semakin baik.

Fungsionalitas ini adalah kunci untuk dapat menulis aturan gaya ekspresif yang menggabungkan alat peraga, kueri media, dan status interaktif. Anda tidak dapat mengganti fungsi itu dengan gaya sebaris. Sayangnya, withStyles tidak dapat digunakan di salah satu proyek saya sampai ini ditambahkan.

Anda selalu dapat menyiapkan tema khusus, dan menggunakan konvensi ini: Kami sangat menyukai bagaimana komponen yang ditata memberi Anda akses ke props.theme di luar kotak dengan menyarangkan ThemeProvider di dalam MuiThemeProvider ketika keduanya disebut theme={theme}. Ini memperluas tema default yang diekspos mui

//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']};
`

Saya hanya perlu menggunakan nilai fungsi, jadi saya menggunakan fungsi injectSheet() react-jss. Saya terbiasa menggunakan fungsi withStyles() Mui, jadi apakah ada kelemahan saat menggunakan injectSheet daripada withStyles?

@damien-monni Anda tidak mendapatkan akses ke tema MUI Anda.

Halo semua, hanya ingin membagikan versi saya tentang API seperti komponen bergaya Material-UI. Ini tidak diuji "berat" tetapi tampaknya berfungsi dengan baik dan menyediakan:

  • Mengangkat props dan theme ke fungsi gaya.
  • Melewati props kustom ke komponen yang dibungkus
  • Meneruskan referensi melalui React.forwardRef
    (EDIT: Ref saat ini hanya berfungsi untuk tag html, bukan sebagian besar komponen Material-UI dasar, ini memerlukan dukungan internal. Mungkin bekerja pada PR ketika saya punya waktu, akan membutuhkan penerimaan function atau object prop-types, dan melakukan pemeriksaan pada komponen stateless apakah akan diteruskan ke child )

Masalah terkait: #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;

Contoh penggunaan

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,
  },
}));

Dengan alat peraga khusus

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

@olivietassinari Untuk mengatasi masalah ini, saya menggunakan solusi di bawah ini:

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

Ini berfungsi dengan baik tetapi apakah ada beberapa masalah potensial yang tidak saya lihat? Saya tidak suka bahwa saya harus menelepon jss.setup dua kali misalnya . Saya tidak yakin saya memahami siklus hidup jss . Saya terkejut bahwa saya perlu memanggil setup() sini.

Ini berfungsi dengan baik tetapi apakah ada beberapa masalah potensial yang tidak saya lihat?

@wcandillon Beberapa masalah potensial yang dapat saya lihat: 1. Anda akan menyuntikkan nama kelas baru setiap kali instance komponen dipasang. 2. Anda tidak akan dapat merender komponen Anda di sisi server. 3. Anda tidak akan mendapatkan urutan injeksi penggantian CSS yang benar.

Saya mengembangkan perpustakaan ini untuk memiliki alat peraga dengan gaya:

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

Diuji dengan sukses pada sebuah proyek.

Pada awalnya, saya menggunakan solusi danielmahon, tetapi mendapatkan masalah pewarisan gaya.

@oliviertasinari Apakah kami memiliki pendekatan alternatif untuk membuat css/animasi dinamis saat ini? Terima kasih :)

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

@danielmahon pendekatan Anda adalah apa yang saya cari saat ini untuk menyelesaikan masalah saya, meskipun "Komponen Bergaya" tidak dirender ulang ketika menerima alat peraga baru. Sudahkah Anda mencoba yang lain?

Saya akan memikirkan sesuatu yang berbeda, dan jika saya menemukan sesuatu, saya akan memberi tahu Anda

Baru saja memasang hadiah $50 untuk yang itu :)

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

Seperti yang dikatakan @lewisdiamond , const styles = (props, theme) => ({}) akan sangat rapi.

Atau const styles = (theme, props) => ({}) mungkin tidak melanggar.

Saya menambahkan masalah ini dalam tonggak sejarah v1.x . Banyak orang yang memintanya. Kami akan segera mendapatkannya.

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

@olivietassinari ini mungkin memiliki implikasi yang signifikan untuk mengetik withStyles , beri tahu saya jika saya dapat membantu dengan itu

@pelotom Terima kasih, saya akan memberi tahu Anda. Saya harap saya bisa mulai melihat masalah ini bulan ini.

Apakah ada pekerjaan yang sedang berlangsung mengenai hal ini? Ini adalah fitur utama IMO, mungkin saya bisa membantu.

EDIT: Saya mulai mengerjakannya. Berhasil meneruskan alat peraga ke fungsi styles yang diterima withStyles , satu-satunya masalah adalah gaya tidak diperbarui ketika alat peraga berubah. Akan membuat PR ketika itu diselesaikan.

Hai Saya baru saja menemukan kasus penggunaan di mana saya membutuhkan ini untuk menyesuaikan warna komponen avatar dan tidak ada cara lain untuk mengontrol gaya untuk semua varian komponen selain ini.

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),
      }),
    },
});

Anda dapat memeriksa solusi saya Japrogramer: https://github.com/JacquesBonet/jss-material-ui

terima kasih, saya akan melihatnya.

Saya membutuhkan fitur ini sebelumnya hari ini jadi saya menulis HOC. withStyles melakukan beberapa caching sendiri jadi saya tidak tahu seberapa besar pengaruhnya, tetapi saya akan melihat implementasi caching withStyles di waktu luang saya, untuk saat ini siapa pun yang mencari cara cepat untuk mendapatkan alat peraga dan tema untuk bermain bagus di sana Anda pergi

Peringatan

Komponen ini akan melakukan remount penuh jika props mengubah sesuatu yang berkaitan dengan nomor indeks dari perubahan kelas stylesheet atau sesuatu di withStyles HOC

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

Contoh penggunaan

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)

kesimpulan

Sederhana dan berfungsi (tetapi rem biaya remount penuh juga)

Dengan perubahan ini, bisakah kita menghapus penggunaan gaya sebaris dari perpustakaan demi 100% JSS? Aplikasi saya tidak berfungsi dengan gaya sebaris dan ketika saya mengganti efek riak dengan JSS, saya menyadari bahwa saya membutuhkan fitur ini. Mungkin hit kinerja kecil, tetapi tampaknya lebih bersih.

@koshea membuang gaya sebaris. Saya juga sangat tidak suka gaya sebaris, itu akan berfungsi dengan baik sebagai pengganti withStyles sebagai dekorator atau seperti pada contoh.

Saya juga ingin menyebutkan, bahwa menggunakan gaya sebaris tidak memungkinkan untuk mengaktifkan Kebijakan Keamanan Konten yang kuat.
Ini membutuhkan penambahan flag unsafe-inline ke arahan gaya, yang tidak aman.

Gaya dinamis dengan dukungan alat peraga harus menyelesaikan masalah itu

Hi guys, maaf untuk melompat ke diskusi "seperti ini". Saya baru-baru ini mulai menggunakan Mui (dengan TypeScript) dan sementara saya merasa itu perpustakaan yang sangat kuat, itu pasti memiliki kompleksitasnya.

Saya perhatikan di beberapa komentar di atas bahwa ada sedikit diskusi apakah fitur ini harus (props, theme) => {} atau (theme, props) => {} . Saya ingin memperkuat apa yang @pelotom katakan tentang membuat properti bernama props dan theme dalam komentarnya . Membuatnya seperti itu mungkin akan memudahkan kita untuk memperbaiki definisi gaya setelah perubahan ini terjadi (yang sangat saya nantikan). Salam

Terima kasih semuanya atas kesabarannya! Masalah ini sedang ditangani di #13503. Ini adalah persyaratan untuk pembantu komponen yang ingin kami implementasikan. Kami juga sudah mulai bereksperimen dengan hook API: https://twitter.com/olivtassinari/status/1058805751404261376.

Apakah ini membuatnya menjadi 4.0? Sepertinya callback makeStyles tidak memiliki parameter props .

@city41 const classes = useStyles(props);

Jadi begitu. Jadi sepertinya begitu

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>;
}

Saya tidak melihat ini didokumentasikan di bagian API gaya di situs web. Biarkan saya melihat apakah saya dapat mengirim PR.

@ city41 Ada awal dokumentasi di https://material-ui.com/styles/basics/#adapting -based-on-props.

keren, senang melihat dokumen diperbarui. untuk siapa pun yang datang ke masalah ini, inilah cara saya menggabungkan tema dan alat peraga untuk menata komponen

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" />;
};

Bagaimana saya bisa menggunakan prop dalam file json gaya eksternal?

misalnya ini adalah file eksternal

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;

saya mengimpor file ini dan menyebarkan objek

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'
                }
            }
        }
    },

  });

sekarang pada fungsi warna saya mendapatkan props = {} .

dapatkah seseorang membantu saya dalam hal ini?

MEMPERBARUI:

sepertinya saya melakukan sesuatu yang salah karena saya mendapatkan objek kosong bahkan di file styles.js utama saya

    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'
                }
            }
        }
    }
},
Apakah halaman ini membantu?
0 / 5 - 0 peringkat

Masalah terkait

TimoRuetten picture TimoRuetten  ·  3Komentar

rbozan picture rbozan  ·  3Komentar

chris-hinds picture chris-hinds  ·  3Komentar

sys13 picture sys13  ·  3Komentar

mb-copart picture mb-copart  ·  3Komentar