如何在类组件中使用useMediaQuery

时间:2020-01-09 21:15:41

标签: javascript reactjs material-ui react-hooks

使用函数作为组件时,您可以使用material-ui中的useMediaQuery钩子。但是,没有任何地方说明如何在类内部使用此钩子。

因此,我进行了一些研究,发现可以通过以下操作在课堂上使用它:

import React from 'react';
import useMediaQuery from '@material-ui/core/useMediaQuery';

const withMediaQuery = (...args) => Component => props => {
  const mediaQuery = useMediaQuery(...args);
  return <Component mediaQuery={mediaQuery} {...props} />;
};

export default withMediaQuery;

但是,当将其添加到这样的类中时:

export default withStyles(styles)(withMediaQuery(Main));

它给了我这个错误:

index.js:1 Warning: Functions are not valid as a React child. This may happen if you return a Component instead of <Component /> from render. Or maybe you meant to call this function rather than return it.

我确实需要使用媒体查询,因为某些变量依赖于它们。这是我想使用媒体查询的类的render方法。

render() {

    const { classes, children } = this.props;

    const isDesktop = useMediaQuery(theme => theme.breakpoints.up('lg'), {
      defaultMatches: true,
    });

    const shouldOpenSidebar = isDesktop ? true : this.state.openSidebar;

    return (
      <div
        className={cc({
          [classes.root]: true,
          [classes.shiftContent]: isDesktop,
        })}>
        <Topbar
          onSidebarOpen={this.handleSidebarOpen}
        />
        <Sidebar
          onClose={this.handleSidebarClose}
          open={shouldOpenSidebar}
          variant={isDesktop ? 'persistent' : 'temporary'}
        />
        <main className={classes.content}>
          {children}
        </main>
      </div>
    );
  }

我已经尝试包装该组件,但是那样我将无法使用变量

2 个答案:

答案 0 :(得分:4)

您没有提供args所需的useMediaQuery,因此Main作为args传递,并且返回了期望该组件的函数。当React尝试渲染(调用该函数)时,返回值是另一个函数,该值不是react子代的值。

调用函数-withMediaQuery并将其传递给媒体查询,然后将Main传递给返回的函数。

示例:

export default withStyles(styles)(withMediaQuery('(min-width:600px)')(Main));

答案 1 :(得分:2)

使用MediaQuery HOC可以将自己限制在仅一个媒体查询上,而不是更好

public postCall(apiUrl: any, itemName: any): Observable<any> {
  const _options = { 
    headers: new HttpHeaders({
      'Content-Type': 'application/json',
      'Authorization': 'Bearer ' + localStorage.getItem('access_token');
    }
  )};
  return this.http.post(this.actionUrl + apiUrl, itemName, _options);
}

这将允许您将多个查询作为数组传递。每个条目将是一个道具名称,然后是查询。


struct uninfo ; // university information
struct uninfo {
    string all;
    string schoolName;
    string subjectName;
    string day;
    string grade;
    int nStudent;
    int nTeacher;
    int nGraduate;
} ;

struct tree
{
   int key ;
   vector<uninfo> list ;
   tree *left ;
   tree *right ;
   //tree *root ;
   int height ; // tree height
}; // related to the data

class data {

    int total ;
    int size ;
    string fileNum ;
    ifstream rFile ;
    ofstream wFile ;

    public:

        int getheight( tree *N )
        {
            if ( N == NULL)
                return 0;
            return N -> height ;
        }
        //data(){ root = NULL ; }
        //tree avltree ;
        tree *root ;
        vector<uninfo> InputList ;
        bool ReadFile( ) ;
        void clear() ;
        void list() ;
        bool SaveData() ;


}; // for data sorting


tree* r( tree *parent ) {  // this is the right spin

    tree *z = new tree() ; // create a new node
    tree *x = new tree() ; // create a new node
    tree tmp ;

    z  = parent -> left ; // set z as the parent's left child

    x = z -> right ; // set x as z's right child

    parent -> left = x ; // set the parent's left child as x

    z -> right = parent ; // set z's right child as the parent

    parent -> height = max( getheight( parent -> left ), getheight( parent -> right ) ) + 1 ; // update the height

    z -> height = max( getheight( z -> left ), getheight( z -> right ) ) + 1 ; // update the height

    return z ; // return z
} // end of right right spin

tree* l( tree *parent ) { // this is the leftspin

    parent = new tree() ;
    tree *z = new tree() ; // create a new node
    tree *x = new tree() ; // create a new node

    z = parent -> right ; // set the z as the current parent's right child

    x = z -> left ; // set x as z's left child

    parent -> right = z ; // set parent's right child as z

    z -> left = parent; // set z's left child as the parent

    z -> height = max( getheight( z -> left ), getheight( z -> right ) ) + 1 ; // update the height

    parent -> height = max( getheight( parent -> left), getheight( parent -> right ) ) + 1 ; // update the height

    return z ; // return z
}// end of the left spin

tree *insert( tree* v, int y )
{
    data tmp ;
    // data tmp ; in order to access the struct in class, i have to create a new data

    if ( tmp.root == nullptr ) // if root == null
    {
        return ( createnode( v -> list.at( y ).nGraduate ) ); // return a int value
    } // if()

    if ( v -> list.at( y ).nGraduate > ( tmp.root -> list.at( y ).nGraduate ) ) // if the num is bigger then the num in root
    {
        tmp.root -> right = insert( tmp.root -> right, v -> list.at( y ).nGraduate ) ; //set the roo's right child as ( put into function createavltree again ) value



        tmp = balance( v , y ) ;
        // this is the code that went wrong
 //error issue : Use of undeclared identifier 'balance'



    } // if()

    else if ( v -> list.at( y ).nGraduate == ( tmp.root -> list.at( y ).nGraduate ) ) // if the num == num in root
    {
        return tmp.root ; // return root
    } // else if(), this condition is not allowed

    else
    {
        tmp.root -> left = insert( tmp.root -> left, tmp.InputList.at( y ).nGraduate ) ; // set root's left child as ( put into funtion createavltree again ) value
    } // else

    tmp.root -> height = 1 + max( tmp.getheight( tmp.root -> left ), tmp.getheight( tmp.root -> right ) ) ; // update the height

    return  v ;

} // end of insert

tree *balance( tree *tmp, int y )
{
    int f = 0 ;
    data t ;

    f = getheight( t.root -> left ) - getheight( t.root -> right ) ; 
    if ( f > 1 ) // if the factor > 1
    {
        if ( ( t.root -> left -> list.at( y ).nGraduate ) > t.InputList.at( y ).nGraduate ) // if the data currently put in is smaller than the current node's left child
        {
            return r( t.root ) ; // do the ll spin
        } // if(), this is the ll spin

        else if ( t.InputList.at( y ).nGraduate > ( t.root -> left -> list.at( y ).nGraduate ) ) // if the data currently put in is bigger than the current node's left child

        {
            t.root -> left = l( t.root -> left ) ; // do a left spin first
            return r( t.root ) ; // then do a right spin
        } // else if(), this is the lr spin

    } // if()

    else if ( -1 > f ) // if -1 > the facor
    {
        if ( t.InputList.at( y ).nGraduate > ( t.root -> right ->  list.at( y ).nGraduate ) ) // if the data currently put in is bigger than the current node's right child
        {
            return r( t.root ); // do the rr spin
        } // if(), this is thr rr spin

        else if ( ( t.root -> right -> list.at( y ).nGraduate ) > t.InputList.at( y ).nGraduate) // if the data currently put in is smaller than the current node's right child
        {
            t.root -> right = r( t.root -> right ) ; // do the right spin first
            return l( t.root ) ; // then do a left spin
        } // else if(), this is the rl spin

    } // else if()

    return tmp ;
} // end of balance

然后您可以在组件中直接在渲染器中请求道具名称

import React from 'react'
import useMediaQuery from '@material-ui/core/useMediaQuery'

export const withMediaQuery = (queries = []) => Component => props => {
  const mediaProps = {}
  queries.forEach(q => {
    mediaProps[q[0]] = useMediaQuery(q[1])
  })
  return <Component {...mediaProps} {...props} />
}