MakeStyles kullanarak bileşenleri nasıl stilize edebilirim ve yine de Material UI'da yaşam döngüsü yöntemlerine sahip olabilirsiniz?


118

makeStyles()Yaşam döngüsü yöntemlerine sahip bir bileşenle kullanmaya çalıştığımda aşağıdaki hatayı alıyorum :

Geçersiz kanca çağrısı. Kancalar yalnızca bir işlev bileşeninin gövdesinin içinde çağrılabilir. Bu, aşağıdaki nedenlerden biri nedeniyle olabilir:

  1. Uyuşmayan React ve oluşturucu sürümleriniz olabilir (React DOM gibi)
  2. Hook Kurallarını çiğniyor olabilirsiniz
  3. Aynı uygulamada birden fazla React kopyasına sahip olabilirsiniz

Aşağıda bu hatayı oluşturan küçük bir kod örneği verilmiştir. Diğer örnekler, sınıfları alt öğelere de atar. MUI'nin belgelerinde, makeStylesyaşam döngüsü yöntemlerini kullanmanın ve kullanmanın başka yollarını gösteren hiçbir şey bulamıyorum .

    import React, { Component } from 'react';
    import { Redirect } from 'react-router-dom';

    import { Container, makeStyles } from '@material-ui/core';

    import LogoButtonCard from '../molecules/Cards/LogoButtonCard';

    const useStyles = makeStyles(theme => ({
      root: {
        display: 'flex',
        alignItems: 'center',
        justifyContent: 'center',
      },
    }));

    const classes = useStyles();

    class Welcome extends Component {
      render() {
        if (this.props.auth.isAuthenticated()) {
          return <Redirect to="/" />;
        }
        return (
          <Container maxWidth={false} className={classes.root}>
            <LogoButtonCard
              buttonText="Enter"
              headerText="Welcome to PlatformX"
              buttonAction={this.props.auth.login}
            />
          </Container>
        );
      }
    }

    export default Welcome;

Yanıtlar:


170

Merhaba, kanca API'si kullanmak yerine, burada belirtildiği gibi Yüksek dereceli bileşen API'sini kullanmalısınız

Sınıf bileşeni ihtiyacınıza uyacak şekilde dokümantasyondaki örneği değiştireceğim

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

const styles = theme => ({
  root: {
    background: 'linear-gradient(45deg, #FE6B8B 30%, #FF8E53 90%)',
    border: 0,
    borderRadius: 3,
    boxShadow: '0 3px 5px 2px rgba(255, 105, 135, .3)',
    color: 'white',
    height: 48,
    padding: '0 30px',
  },
});

class HigherOrderComponent extends React.Component {

  render(){
    const { classes } = this.props;
    return (
      <Button className={classes.root}>Higher-order component</Button>
      );
  }
}

HigherOrderComponent.propTypes = {
  classes: PropTypes.object.isRequired,
};

export default withStyles(styles)(HigherOrderComponent);

4
Bu hata ve invalid hook callhatayla daireler çizip duruyorum - Beni doğru yöne götürdüğün için teşekkürler !!
Kitson

1
@ Jax-p çözümümü gör
Matt Weber

4
@VikasKumar Bu yaklaşımla stillerimde uygulama temasını nasıl kullanabilirim? Fe submit: {margin: appTheme.spacing (3, 0, 2),},
Sergey Aldoukhov

1
Teşekkürler. Ama bir sorun! Sen kullanmıyordu themesizin de styles(@SergeyAldoukhov zaten bu söylemiştir) vücuda. : Ben kullandığınızda, bu hatayı alıyorum "tanımsız malı 'X' okunamıyor" ve undefinedolduğunu themetam olarak! Denedim withStyles(styles(myDefinedMuiTheme))(...)ve doğru çalıştı.
Mir-İsmaili

1
@Kitson, Muhtemelen makeStyles() ( styles = makeStyles(theme => ({...})) kullandınız . Ayrıca, temaya bağlı stil istiyorsanız, önceki yorumuma bakın.
Mir-İsmaili

41

Kullandığım withStylesyerinemakeStyle

EX:

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

const useStyles = theme => ({
        root: {
           flexGrow: 1,
         },
  });

class App extends Component {
       render() {
                const { classes } = this.props;
                return(
                    <div className={classes.root}>
                       Test
                </div>
                )
          }
} 

export default withStyles(useStyles)(App)

19

Ne, sınıf bileşenleri ve oluşturulan Fonksiyonel Bileşenleri kullanılarak durduruldu yapıyor sona erdi kullanarakuseEffect() gelen yaşam döngüsü yöntemleri için Kancalar API . Bu, Yüksek Dereceli Bileşenler oluşturma karmaşıklığını eklemedenmakeStyles() Yaşam Döngüsü Yöntemleri ile kullanmaya devam etmenize olanak tanır . Hangisi çok daha basit.

Misal:

import React, { useEffect, useState } from 'react';
import axios from 'axios';
import { Redirect } from 'react-router-dom';

import { Container, makeStyles } from '@material-ui/core';

import LogoButtonCard from '../molecules/Cards/LogoButtonCard';

const useStyles = makeStyles(theme => ({
  root: {
    display: 'flex',
    alignItems: 'center',
    justifyContent: 'center',
    margin: theme.spacing(1)
  },
  highlight: {
    backgroundColor: 'red',
  }
}));

// Highlight is a bool
const Welcome = ({highlight}) => { 
  const [userName, setUserName] = useState('');
  const [isAuthenticated, setIsAuthenticated] = useState(true);
  const classes = useStyles();

  useEffect(() => {
    axios.get('example.com/api/username/12')
         .then(res => setUserName(res.userName));
  }, []);

  if (!isAuthenticated()) {
    return <Redirect to="/" />;
  }
  return (
    <Container maxWidth={false} className={highlight ? classes.highlight : classes.root}>
      <LogoButtonCard
        buttonText="Enter"
        headerText={isAuthenticated && `Welcome, ${userName}`}
        buttonAction={login}
      />
   </Container>
   );
  }
}

export default Welcome;

2
React 16.8 Hooks güncellemesini veya daha üstünü kullanan kişiler için, bir işleve geçmenin ideal bir çözüm olduğunu düşünüyorum. 16.8'de işlevler durum ve yaşam döngüsü kancalarına erişebilir.
Tim

5
Bunun neden olumsuz oy aldığına şaşıyorum. React, sınıfların Hook'lu işlevsel bileşenlerle değiştirildiğini oldukça açık hale getirdi. reactjs.org/docs/…
Matt Weber

3
Olumsuz oy vermedim, ancak işlev tabanlı bileşeni kullanırken xhr kullanarak başlangıç ​​durumunu tembel bir şekilde ayarlamak acı verici. Sınıf bileşeni ile ilk durumunu istediğim gibi ayarlayabilirim, ardından ajax'ı ve ardından yanıt geldiğinde setState'i kullanabilirim. Bir işlevle nasıl güzelce yapılacağına dair hiçbir fikrim yok.
mlt

1
Kullanırdın useEffect. Yukarıdaki durumda, userName'in başlangıç ​​durumunu boş bir dizeye ayarlıyorsunuz, ardından useEffectkullanacağınızdan emin olduğunuz bir API çağrısı yapıldıktan sonra setUserName(response). Yukarıda bir örnek ve useEffect'in yaşam döngüsü yöntemleri için kullanımı hakkında daha fazla bilgi içeren bir makaleye bağlantı ekleyeceğim. dev.to/prototyp/…
Matt Weber

3
Bu, mimariye ihtiyaç duyan gerçek uygulamalarda işlevsel programlama berbat olduğu için oylanıyor. Js programcılarının, okuması / takip etmesi gerçekten çok zor olan ve makul bileşenlere ayrılması imkansız olan büyük spagetti kodu oluşturma eğilimini artırıyor. Eğer tepki bu şekilde zorluyorsa büyük bir hata yapıyorlar ve ben onları orada takip etmeyeceğim.
RickyA

2

useStyles fonksiyonel bileşenlerde kullanılması amaçlanan ve sınıf bileşenlerinde kullanılamayan bir React kancadır.

React'ten:

Hook'lar, bir sınıf yazmadan durum ve diğer React özelliklerini kullanmanıza izin verir.

Ayrıca işlevinizin içinde aşağıdaki gibi useStyleshook çağırmalısınız ;

function Welcome() {
  const classes = useStyles();
...

Kancaları kullanmak istiyorsanız, işte kısa sınıf bileşeniniz işlevsel bileşene değiştirildi;

import React from "react";
import { Container, makeStyles } from "@material-ui/core";

const useStyles = makeStyles({
  root: {
    background: "linear-gradient(45deg, #FE6B8B 30%, #FF8E53 90%)",
    border: 0,
    borderRadius: 3,
    boxShadow: "0 3px 5px 2px rgba(255, 105, 135, .3)",
    color: "white",
    height: 48,
    padding: "0 30px"
  }
});

function Welcome() {
  const classes = useStyles();
  return (
    <Container className={classes.root}>
      <h1>Welcome</h1>
    </Container>
  );
}

export default Welcome;

🏓 üzerinde ↓ CodeSandBox ↓

React kancalarını düzenle


0

Sınıf bileşenleri için başka bir çözüm de kullanılabilir - sadece varsayılan MUI Theme özelliklerini MuiThemeProvider ile geçersiz kılın. Bu, diğer yöntemlere kıyasla daha fazla esneklik sağlayacaktır - üst bileşeninizin içinde birden fazla MuiThemeProvider kullanabilirsiniz.

basit adımlar:

  1. MuiThemeProvider'ı sınıf bileşeninize içe aktarın
  2. createMuiTheme'yi sınıf bileşeninize aktarın
  3. yeni tema oluştur
  4. MuiThemeProvider ve özel temanızla stil vermek istediğiniz hedef MUI bileşenini sarın

daha fazla ayrıntı için lütfen bu belgeye bakın: https://material-ui.com/customization/theming/

import React from 'react';
import PropTypes from 'prop-types';
import Button from '@material-ui/core/Button';

import { MuiThemeProvider } from '@material-ui/core/styles';
import { createMuiTheme } from '@material-ui/core/styles';

const InputTheme = createMuiTheme({
    overrides: {
        root: {
            background: 'linear-gradient(45deg, #FE6B8B 30%, #FF8E53 90%)',
            border: 0,
            borderRadius: 3,
            boxShadow: '0 3px 5px 2px rgba(255, 105, 135, .3)',
            color: 'white',
            height: 48,
            padding: '0 30px',
        },
    }
});

class HigherOrderComponent extends React.Component {

    render(){
        const { classes } = this.props;
        return (
            <MuiThemeProvider theme={InputTheme}>
                <Button className={classes.root}>Higher-order component</Button>
            </MuiThemeProvider>
        );
    }
}

HigherOrderComponent.propTypes = {
    classes: PropTypes.object.isRequired,
};

export default HigherOrderComponent;


-1

Sınıfı bir işleve dönüştürmek yerine, kolay bir adım, 'sınıfları' kullanan bileşen için jsx'i içerecek bir işlev oluşturmaktır, sizin durumunuzda, <container></container>ve sonra bu işlevi sınıfın dönüşü içinde çağırın render () etiket olarak. Bu şekilde, kancayı sınıftan bir işleve taşıyorsunuz. Benim için mükemmel çalıştı. Benim durumumda, bir <table>işleve dışarıdaki TableStmt işlevine taşındım ve bu işlevi render içinde olarak adlandırdım<TableStmt/>

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.