2017-05-28 181 views
1

調用子組件的功能時,材料的UI抽屜沒有迴環我有App.js陣營從父

import React, { Component } from 'react'; 
import logo from './logo.svg'; 
import './App.css'; 
import Child from './child'; 

class App extends Component { 
    render() { 
    return (
     <div className="App"> 
     <div className="App-header"> 
      <img src={logo} className="App-logo" alt="logo" /> 
      <h2>Welcome to React</h2> 
     </div> 
     <p className="App-intro"> 
      To get started, edit <code>src/App.js</code> and save to reload. 
     </p> 
     <Child ref={instance => { this.child = instance; }}/> 
      <button onClick={() => { this.child.onAlert(); }}>Click</button> 
     </div> 
    ); 
    } 
} 

export default App; 

而像

import React, { Component } from 'react'; 

class Child extends Component { 
    state = { } 
    onAlert =()=> 
     alert("hey"); 
    render() { 
     return (
      <div> IM kid</div> 
     ); 
    } 
} 

export default Child; 

這裏當我點擊按鈕的子組件的樣本代碼在App.js我能夠得到預期的輸出 即,我可以調用子函數onAlert()

我在material-ui中使用相同的場景並對wh趁着我需要從工具欄組件

觸發抽屜組件和我的代碼就像下面的代碼Titlebar.js在這裏我父組件

import React, { Component } from 'react'; 
import PropTypes from 'prop-types'; 
import Toolbar from 'material-ui/Toolbar' 
import AppBar from 'material-ui/AppBar'; 
import Typography from 'material-ui/Typography'; 
import IconButton from 'material-ui/IconButton'; 
import MenuIcon from 'material-ui-icons/Menu'; 

import { withStyles, createStyleSheet } from 'material-ui/styles'; 
import Child from './child'; 



const styleSheet = createStyleSheet('Titlebar',() => ({ 

    root: { 
     position: 'relative', 
     width: '100%', 
    }, 
    appBar: { 
     position: 'relative', 
    }, 
    flex: { 
     flex: 1, 
    } 
})); 

class TitleBar extends Component { 
    render() { 
     const classes = this.props.classes; 
     return (
      <div className={classes.root}> 
       <AppBar className={classes.appBar}> 
        <Toolbar> 
         <IconButton contrast onClick={() => { this.child.handleLeftOpen(); }}> 
          <MenuIcon /> 
         </IconButton> 
         <Typography type="title" colorInherit className={classes.flex}>Productivity Dashboard</Typography> 
        </Toolbar> 
       </AppBar> 
       <Child ref={instance => { this.child = instance; }}/> 
      </div> 
     ) 
    } 
} 

TitleBar.PropTypes={ 
    classes:PropTypes.object.isRequired, 
} 

export default withStyles(styleSheet)(TitleBar); 

和我的孩子組件代碼Child.js低於

import React, { Component } from 'react'; 
import { withStyles, createStyleSheet } from 'material-ui/styles'; 
import Drawer from 'material-ui/Drawer'; 
import List, { ListItem, ListItemIcon, ListItemText } from 'material-ui/List'; 
import Divider from 'material-ui/Divider'; 
import InboxIcon from 'material-ui-icons/Inbox'; 
import DraftsIcon from 'material-ui-icons/Drafts'; 
import StarIcon from 'material-ui-icons/Star'; 
import SendIcon from 'material-ui-icons/Send'; 
import MailIcon from 'material-ui-icons/Mail'; 
import DeleteIcon from 'material-ui-icons/Delete'; 
import ReportIcon from 'material-ui-icons/Report'; 

const styleSheet = createStyleSheet('Child', { 
    list: { 
    width: 250, 
    flex: 'initial', 
    }, 
    listFull: { 
    width: 'auto', 
    flex: 'initial', 
    }, 
}); 
class Child extends Component { 
    state = { 
    open: { 
     top: false, 
     left: false, 
     bottom: false, 
     right: false, 
    }, 
    } 
handleLeftOpen =() =>{ 
      console.log("im here") 
      this.toggleDrawer('left', true); 
     } 
     handleLeftClose =() => this.toggleDrawer('left', false); 
    toggleDrawer = (side, open) => { 
    const drawerState = {}; 
    drawerState[side] = open; 
    this.setState({ open: drawerState }); 
    }; 
    render() { 
     const classes=this.props.classes; 
     return (
      <Drawer 
      open={this.state.open.left} 
      onRequestClose={this.handleLeftClose} 
      onClick={this.handleLeftClose} 
     > 
     <List className={classes.list} disablePadding> 
      <ListItem button> 
      <ListItemIcon> 
      <InboxIcon /> 
      </ListItemIcon> 
      <ListItemText primary="Inbox" /> 
     </ListItem> 
     <ListItem button> 
      <ListItemIcon> 
      <StarIcon /> 
      </ListItemIcon> 
      <ListItemText primary="Starred" /> 
     </ListItem> 
     <ListItem button> 
      <ListItemIcon> 
      <SendIcon /> 
      </ListItemIcon> 
      <ListItemText primary="Send mail" /> 
     </ListItem> 
     <ListItem button> 
      <ListItemIcon> 
      <DraftsIcon /> 
      </ListItemIcon> 
      <ListItemText primary="Drafts" /> 
     </ListItem> 
     </List> 
     <Divider /> 
     <List className={classes.list} disablePadding> 
      <ListItem button> 
      <ListItemIcon> 
      <MailIcon /> 
      </ListItemIcon> 
      <ListItemText primary="All mail" /> 
     </ListItem> 
     <ListItem button> 
      <ListItemIcon> 
      <DeleteIcon /> 
      </ListItemIcon> 
      <ListItemText primary="Trash" /> 
     </ListItem> 
     <ListItem button> 
      <ListItemIcon> 
      <ReportIcon /> 
      </ListItemIcon> 
      <ListItemText primary="Spam" /> 
     </ListItem> 
     </List> 
       </Drawer> 
     ); 
    } 
} 

export default withStyles(styleSheet)(Child); 

在這裏,我從我的父母調用handleLeftOpen()函數時,我單擊Tiltlbar組件中的IconButton我沒有得到預期的輸出。我收到錯誤,如下面在我的控制檯

Uncaught TypeError: Cannot read property 'handleLeftOpen' of null 
    at onClick (http://localhost:3000/static/js/bundle.js:90993:50) 
    at Object.ReactErrorUtils.invokeGuardedCallback (http://localhost:3000/static/js/bundle.js:17236:17) 
    at executeDispatch (http://localhost:3000/static/js/bundle.js:17019:22) 
    at Object.executeDispatchesInOrder (http://localhost:3000/static/js/bundle.js:17042:6) 
    at executeDispatchesAndRelease (http://localhost:3000/static/js/bundle.js:16430:23) 
    at executeDispatchesAndReleaseTopLevel (http://localhost:3000/static/js/bundle.js:16441:11) 
    at Array.forEach (native) 
    at forEachAccumulated (http://localhost:3000/static/js/bundle.js:17339:10) 
    at Object.processEventQueue (http://localhost:3000/static/js/bundle.js:16644:8) 
    at runEventQueueInBatch (http://localhost:3000/static/js/bundle.js:24266:19) 

請檢查代碼,讓我知道如果有什麼需要改變

回答

1

這裏的區別是,在你的第一個例子中,你導出:

export default Child; 

在第二個例子中,你導出:

export default withStyles(styleSheet)(Child); 

這將返回裝飾組件,所以ref放在這個裝飾組件上,而不是你的子組件。爲了解決這個問題,裝飾組件接受一個名爲innerRef的屬性,這樣你就可以將ref傳遞給你自己的組件。因此,要解決這個問題,你的變化:

<Child ref={instance => { this.child = instance; }}/> 

<Child innerRef={instance => { this.child = instance; }}/>