Material-ui: [withStyles]スタイルオブジェクト内からコンポーネントの小道具を取得する機能を追加します

作成日 2017年08月02日  ·  39コメント  ·  ソース: mui-org/material-ui

説明

createStyleSheetを使用する場合、コンポーネントの小道具にアクセスする方法はありません(少なくとも私が知っていることです)。 サイズ、URL画像、その他のスタイルを小道具としてコンポーネントに渡したい場合があるため、これは重要だと思います。

今日、これに対する唯一の解決策は、これらのものをインラインスタイルに分離することですが、私が知る限り、material-ui v1はjssreact-jssを使用し、これら2つはすでに可能性を提供しています小道具を受け取り、次のように目的のスタイルを返す関数を介して小道具にアクセスします。

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

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

そのようなものをmaterial-uiにも実装することについてどう思いますか?

enhancement important

最も参考になるコメント

この問題をv1.xマイルストーンに追加します。 多くの人がそれを要求しています。 すぐに到達します。

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

全てのコメント39件

react-jssはその機能を実装します。 あなたはいつでも私たちのスタイリングソリューションの上でそれを使うことができます。 ここでその機能を実装する本当の動機は、コンポーネントのより単純でより良い内部実装にあるはずです。

react-jss injectStyles()もこれを行いますが、 StyleRuleCallback小道具を追加する方が良いようです。

const styles = (props, theme) => ({})
そうすれば、小道具に応じた値だけに制限されることはありません。

@Shamplolのフィードバックにより、この新機能を利用して、ユーザーが事前定義されたものではなく、カスタムのcolorをコンポーネントに提供できるようになる可能性があると思います。 CSSサイズへの影響は明確ではありませんが、コンポーネントの色のオーバーライドがさらに簡単になります。 これは調査するものです。 次に、css変数ブラウザーのサポートが十分に高くなると(2年後?)、それを信頼できます。

@oliviertassinari cssサイズが実際に減少しない場合がありますか?
私が理解したように、現在、すべてのクラスを...Primary...Accent定義しています-この変更は、 ...Colorizedクラスを維持するだけでよいという意味ではありませんか? または、生成されたcssについて心配していますか?

いずれにせよ、 https://github.com/callemall/material-ui/blob/v1-beta/src/Button/Button.js#L11のような複雑なクラスを基本的に再実装する必要があるため、これによりdxが大幅に改善されると思います。パレット以外の色を使用したい。

場合によっては、CSSのサイズが実際に減少することはありませんか?

@sakulstraわかりにくい。 実装によって異なります。 多分 :)。

TypeScriptタイピングの観点からは、スタイル仕様内で_both_ propsthemeこの方法でアクセスできると便利です。

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

その理由は、TypeScriptが関数オブジェクトを渡されたときにwithStylesの正しい型を推測できないことが多いため、それを機能させるには追加の型注釈を提供する必要があります。

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

小道具も渡されると、これは

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

これの現状はどうですか? その機能があると本当にいいでしょう

@lucasmafraこの機能をv1リリース後のマイルストーンに追加しました。 v1をリリースするのが早ければ早いほど良いです。

この機能は、小道具、メディアクエリ、インタラクティブな状態を組み合わせた表現力豊かなスタイルのルールを作成できるようにするための鍵です。 その機能をインラインスタイルに置き換えることはできません。 残念ながら、 withStylesは、これが追加されるまで、どのプロジェクトでも使用できません。

いつでもカスタムテーマを設定し、次の規則を使用できます。両方がtheme = {theme}と呼ばれる場合、MuiThemeProvider内にThemeProviderをネストすることで、スタイル付きコンポーネントがすぐにprops.themeにアクセスできる方法が非常に気に入っています。 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']};
`

関数値を使用する必要があったので、react-jssのinjectSheet()関数を使用しました。 私はMuiのwithStyles()関数を使用することに慣れていますが、withStylesの代わりにinjectSheetを使用する場合、何か欠点はありますか?

@ damien-monniMUIテーマにアクセスできません。

みなさん、こんにちは。私のバージョンのMaterial-UI styled-components-likeAPIを共有したかっただけです。 「徹底的に」テストされていませんが、うまく機能しているようで、次の機能を提供します。

  • propsthemeを持ち上げて機能をスタイルします。
  • カスタムpropsをラップされたコンポーネントに渡す
  • React.forwardRefを介して
    (編集:Refsは現在htmlタグに対してのみ機能しており、ほとんどの基本的なMaterial-UIコンポーネントでは機能していません。これには内部サポートが必要です。時間があれば、PRで機能する可能性があり、 functionまたはobject受け入れる必要があります。

関連する問題:#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;

使用例

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

カスタム小道具付き

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

@oliviertassinariこの問題を解決するために、私は以下の解決策を使用しています:

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

それはうまく機能しますが、私が見ていないいくつかの潜在的な問題がありますか? たとえば、jss.setupを2回呼び出さなければならないのは好きではありません😅。 jssライフサイクルを理解しているかどうかわかりません。 ここでsetup()を呼び出す必要があることに驚きました。

それはうまく機能しますが、私が見ていないいくつかの潜在的な問題がありますか?

@wcandillon私が見ることができるいくつかの潜在的な問題:1。コンポーネントのインスタンスがマウントされる

私はこのライブラリを開発して、スタイルのある小道具を用意しました。

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

プロジェクトで正常にテストされました。

最初はダニエルマホンソリューションを使用しますが、スタイル継承の問題が発生します。

@oliviertassinari現時点で動的なCSS /アニメーションを作成するための代替アプローチはありますか? ありがとう :)

@HunderlineKいくつかの選択肢: https ://material-ui.com/customization/overrides/#2-dynamic-variation-for-a-one-time-situation。

@danielmahonあなたのアプローチは、私の問題を解決するために今私が探しているものですが、「スタイル付きコンポーネント」は新しい小道具を受け取ったときに再レンダリングされません。 他に何か試したことはありますか?

何か違うことを考えて、思いついたらお知らせします

💰ちょうどそれに50ドルの賞金を付けました:)

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

@lewisdiamondが言ったように、 const styles = (props, theme) => ({})は本当にきれいでしょう。

または、 const styles = (theme, props) => ({})を壊さないようにすることもできます。

この問題をv1.xマイルストーンに追加します。 多くの人がそれを要求しています。 すぐに到達します。

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

@oliviertassinariこれはおそらくwithStylesの入力に重大な影響を及ぼします、私がそれを手伝うことができるかどうか私に知らせてください

@pelotomありがとうございます。お知らせします。 今月からこの問題を検討し始めたいと思います。

これに関して進行中の作業はありますか? これはIMOの重要な機能であり、おそらく私はそれを手伝うことができます。

編集:私はそれに取り組み始めました。 withStyles受け入れるstyles関数に小道具を渡すことができました。問題は、小道具が変更されてもスタイルが更新されないことだけです。 それが解決されたときにPRを作成します。

こんにちは私はアバターコンポーネントの色をカスタマイズするためにこれが必要なユースケースに出くわしました。これ以外にコンポーネントのすべてのバリエーションのスタイルを制御する方法は他にありません。

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

私のソリューションJaprogramerを確認できます//github.com/JacquesBonet/jss-material-ui

おかげで、私はそれを見ていきます。

今日はこの機能が必要だったので、HOCを作成しました。 withStylesはそれ自体でキャッシュを実行するため、これがどの程度影響するかはわかりませんが、空き時間にwithStylesのキャッシュ実装を確認します。小道具やテーマを上手にプレイするための簡単な方法

警告

小道具がスタイルシートクラスのインデックス番号の変更またはwithStylesHOCの何かに関係する何かを変更した場合、このコンポーネントは完全な再マウントを行います

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

使用例

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)

結論

シンプルで機能します(ただし、再マウントの全費用もかかります)

この変更により、100%JSSを優先して、ライブラリからインラインスタイルの使用を削除できますか? 私のアプリはインラインスタイルでは動作しません。波及効果をJSSに置き換えようとしたときに、この機能が必要であることに気付きました。 パフォーマンスに小さな影響があるかもしれませんが、よりクリーンに見えます。

@kosheaはインラインスタイルを捨てます。 また、インラインスタイルも本当に好きではありません。デコレータとして、または例のように、 withStyles代わりにドロップとして問題なく機能するはずです。

また、インラインスタイルを使用しても、強力なコンテンツセキュリティポリシーを有効にできないことにも言及したいと思います。
スタイルディレクティブにunsafe-inlineフラグを追加する必要がありますが、これは安全ではありません。

小道具をサポートする動的スタイルは、その問題を解決する必要があります

こんにちはみんな、「このように」議論に飛び込んで申し訳ありません。 私は最近Mui(Typescriptを使用)を使い始めました。これは非常に強力なライブラリですが、確かに複雑です。

上記のいくつかのコメントで、この機能を(props, theme) => {}(theme, props) => {}するかについて少し議論があることに気づきました。 @pelotomが彼のコメントでpropstheme両方の名前付きプロパティ作成することについて言ったことを強調したいと思います。 そうすることで、この変更が行われた後、スタイル定義をリファクタリングするのが簡単になるでしょう(私は本当に楽しみにしています)。 乾杯🙂

お待ちいただき、ありがとうございます。 この問題は#13503で処理されています。 これは、実装するコンポーネントヘルパーの要件です。 フックAPIの実験も開始しました: https

これで4.0になりましたか? makeStylesコールバックにpropsパラメータがないようです。

@ city41 const classes = useStyles(props);

分かりました。 だからそれはそうです

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

ウェブサイトのstylesAPIセクションにこれが記載されていません。 PRを送れるか見てみましょう。

@ city41は、内のドキュメントの開始がありhttps://material-ui.com/styles/basics/#adaptingベースのオン小道具。

ドキュメントが更新されているのを見てうれしいです。 この問題に来る他の人のために、これが私がどのようにテーマと小道具を組み合わせてコンポーネントをスタイリングしたかです

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

外部スタイルのjsonファイルでpropを使用するにはどうすればよいですか?

たとえば、これは外部ファイルです

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;

このファイルをインポートしてオブジェクトを広げます

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

  });

今カラー関数で私は小道具= {}を取得します。

誰かがこの点で私を助けることができますか?

アップデート:

メインのstyles.jsファイルでも空のオブジェクトを取得しているため、何か間違ったことをしているようです

    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'
                }
            }
        }
    }
},
このページは役に立ちましたか?
0 / 5 - 0 評価