makeStyles를 사용하여 구성 요소의 스타일을 지정하고 머티리얼 UI에 여전히 수명주기 메서드가있는 방법은 무엇입니까?


119

makeStyles()수명주기 메서드와 함께 구성 요소 를 사용하려고 할 때마다 아래 오류가 발생 합니다.

잘못된 후크 호출입니다. 후크는 함수 구성 요소의 본문 내에서만 호출 할 수 있습니다. 이는 다음 이유 중 하나로 인해 발생할 수 있습니다.

  1. React와 렌더러 (예 : React DOM)의 버전이 일치하지 않을 수 있습니다.
  2. 후크 규칙을 위반할 수 있습니다.
  3. 동일한 앱에 둘 이상의 React 사본이있을 수 있습니다.

다음은이 오류를 생성하는 코드의 작은 예입니다. 다른 예에서는 하위 항목에도 클래스를 할당합니다. 다른 사용 방법을 보여주고 makeStyles수명주기 방법을 사용할 수있는 기능이있는 MUI 문서에서 아무것도 찾을 수 없습니다 .

    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;

답변:


173

안녕하세요, 후크 API를 사용하는 대신 여기 에서 언급 한 고차 컴포넌트 API를 사용해야 합니다.

클래스 구성 요소에 대한 필요에 맞게 설명서의 예제를 수정하겠습니다.

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
나는이 버그와 invalid hook call오류 로 원을 그리며 달리고 있었습니다. 올바른 방향으로 안내해 주셔서 감사합니다!
Kitson

1
JAX-P @ 내 솔루션을 참조
매트 웨버

4
@VikasKumar이 접근 방식을 사용하면 내 스타일에서 앱 테마를 어떻게 사용할 수 있습니까? Fe 제출 : {margin : appTheme.spacing (3, 0, 2),},
Sergey Aldoukhov

1
감사. 그러나 문제! 당신은 사용하지 않는 theme사용자에 styles(@SergeyAldoukhov 이미이 말했다) 몸. : 나는 그것을 사용하는 경우,이 오류 "정의되지 않은 재산 'X'를 읽을 수 없습니다" 하고 undefined있다 theme정확하게! 나는 시도 withStyles(styles(myDefinedMuiTheme))(...)했고 제대로 작동했습니다.
Mir-Ismaili

1
@Kitson, 아마도 makeStyles() ( styles = makeStyles(theme => ({...})) 을 사용했을 것 입니다. 또한 테마별 스타일을 원한다면 이전 댓글을 참조하세요.
Mir-Ismaili

43

withStyles대신 사용makeStyle

예 :

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

우리가, 클래스 구성 요소와 생성 기능 컴포넌트를 사용 중지하고 결국 사용useEffect() 으로부터 수명주기 방법에 대한 후크의 API . 이를 통해 고차 구성 요소를 만드는 복잡한 작업을 추가하지 않고도makeStyles() 수명주기 메서드 를 계속 사용할 수 있습니다 . 훨씬 간단합니다.

예:

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 업데이트 이상을 사용하는 사람들에게는 함수로 전환하는 것이 이상적인 솔루션이라고 생각합니다. 16.8에서 함수는 상태 및 수명주기 후크에 액세스 할 수 있습니다.
Tim

5
나는 이것이 왜 반대표를 받았는지 당황합니다. React는 클래스가 후크를 사용하는 기능적 구성 요소로 대체되고 있음을 명확하게했습니다. reactjs.org/docs/…
Matt Weber

3
나는 downvote하지 않았지만 함수 기반 구성 요소를 사용하는 동안 xhr을 사용하여 초기 상태를 게으른 방식으로 설정하는 것이 고통 스럽습니다. 클래스 구성 요소를 사용하면 초기 상태를 원하는대로 설정 한 다음 응답이 도착하면 ajax를 사용한 다음 setState를 사용할 수 있습니다. 함수로 멋지게하는 방법을 전혀 모르겠습니다.
mlt

1
당신은 useEffect. 경우에 당신이 빈 문자열로 사용자 이름 초기 상태를 설정하는 이상, 다음 수행 API 호출 이후의 보험 useEffect사용하는 것이 당신 setUserName(response). 위의 예제와 수명주기 메서드에 대한 useEffect의 사용에 대한 자세한 정보가있는 아티 컬 링크를 추가하겠습니다. dev.to/prototyp/…
Matt Weber

3
함수형 프로그래밍이 아키텍처를 필요로하는 실제 응용 프로그램을 짜증나게했기 때문에 이것은 투표를 받고 있습니다. 그것은 js 프로그래머가 읽고 / 따르기가 정말 어렵고 합리적인 구성 요소로 분리 할 수없는 커다란 스파게티 코드를 만드는 경향이 이미 확산되고 있습니다. 리 액트가 이런 식으로 밀어 붙이면 그들은 큰 실수를 저지르고 있으며 나는 그들을 따르지 않을 것입니다.
RickyA

2

useStyles 기능적 구성 요소에서 사용하기위한 React 후크이며 클래스 구성 요소에서는 사용할 수 없습니다.

React에서 :

후크를 사용하면 클래스를 작성하지 않고도 상태 및 기타 React 기능을 사용할 수 있습니다.

또한 useStyles후크 를 호출해야 과 같이 함수 내에서 .

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

후크를 사용하려면 다음은 기능적 구성 요소로 변경된 간단한 클래스 구성 요소입니다.

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;

🏓 on ↓ CodeSandBox ↓

React 후크 편집


0

클래스 구성 요소에 또 다른 솔루션을 사용할 수 있습니다. 기본 MUI 테마 속성을 MuiThemeProvider로 재정의하기 만하면됩니다. 이렇게하면 다른 메서드에 비해 더 많은 유연성이 제공됩니다. 부모 구성 요소 내에서 둘 이상의 MuiThemeProvider를 사용할 수 있습니다.

간단한 단계 :

  1. MuiThemeProvider를 클래스 구성 요소로 가져옵니다.
  2. createMuiTheme를 클래스 구성 요소로 가져옵니다.
  3. 새로운 테마 만들기
  4. MuiThemeProvider 및 사용자 지정 테마로 스타일을 지정할 대상 MUI 구성 요소를 래핑합니다.

자세한 내용은이 문서를 확인하십시오 : 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

클래스를 함수로 변환하는 대신 쉬운 단계는 '클래스'를 사용하는 구성 요소에 대한 jsx를 포함하는 함수를 만드는 것입니다. 귀하의 경우에는 <container></container>이 함수를 render () 클래스의 반환 내에서 호출하십시오. 태그로. 이런 식으로 클래스에서 함수로 후크를 이동합니다. 그것은 나를 위해 완벽하게 작동했습니다. 제 경우에는 <table>외부의 TableStmt 함수로 이동하고 렌더링 내부 에서이 함수를 다음과 같이 호출했습니다.<TableStmt/>

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.