如何将Material-UI的快餐栏和输入组件结合在一起进行反应?

时间:2018-11-18 20:40:33

标签: javascript reactjs design-patterns material-ui

我正在使用Material-UI组件来构建我的网站。我有一个带有搜索字段的标头组件,该字段在后台使用mui InputBase。当用户输入空输入时(也就是说,他们什么也不输入,只需单击Enter),我想显示一个mui Snackbar,该警告会警告用户没有输入任何有意义的输入。

我无法将两个组件结合在一起使用。另外,由于当用户不输入任何内容时,搜索字段的状态并没有真正改变,因此不会重新加载,因此,如果用户反复按Enter键,则不会出现小吃栏。我使用this.forceUpdate();,但是有没有更优雅的方法来实现这种逻辑呢?

这是我的代码:

对于搜索输入字段:

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import InputBase from '@material-ui/core/InputBase';
import { withStyles } from '@material-ui/core/styles';
import { withRouter } from 'react-router-dom';
import { connect } from 'react-redux';
import { getAppInfo } from '../../actions/appActions.js';
import constants from '../../constants.js';

import { AppSearchBarInputStyles } from '../styles/Material-UI/muiStyles.js';
import AppNotFound from './AppNotFound.js';

class AppSearchBarInput extends Component {
  state = {
    appId: ''
  }

  onChange = e => {
    this.setState({ appId: e.target.value });
  }

  onKeyDown = e => {
    const { appId } = this.state;

    if (e.keyCode === constants.ENTER_KEY && appId !== '') {
      this.props.getAppInfo({ appId });
      this.setState({
        appId: ''
      });
    }
    this.props.history.push('/app/appInfo');
    this.forceUpdate();
  }

  render() {
    const { classes } = this.props;
    const { appId } = this.state;
    console.log(`appId from AppSearchInput=${appId === ''}`);

    return (
      <div>
        <InputBase
          placeholder="Search…"
          classes={{
            root: classes.inputRoot,
            input: classes.inputInput,
          }}
          onChange={this.onChange}
          onKeyDown={this.onKeyDown}
          value={this.state.appId} />
        { appId === '' ? <AppNotFound message={constants.MESSAGES.APP_BLANK()}/> : ''}
      </div>
    )
  }
}

AppSearchBarInput.propTypes = {
  classes: PropTypes.object.isRequired
}

const AppSearchBarWithStyles = withStyles(AppSearchBarInputStyles)(AppSearchBarInput);
const AppSearchBarWithStylesWithRouter = withRouter(AppSearchBarWithStyles);
export default connect(null, { getAppInfo })(AppSearchBarWithStylesWithRouter);

小吃栏:

import React from 'react';
import Snackbar from '@material-ui/core/Snackbar';
import constants from '../../constants.js';
import SnackbarMessage from './SnackbarMessage.js';


class AppNotFound extends React.Component {
  state = {
    open: true,
  };

  handleClose = event => {
    this.setState({ open: false });
  };

  render() {
    const { message } = this.props;
    return (
      <Snackbar
        anchorOrigin={{
          vertical: 'top',
          horizontal: 'center',
        }}
        open={this.state.open}
        autoHideDuration={6000}
        onClose={this.handleClose}
      >
        <SnackbarMessage
          onClose={this.handleClose}
          variant="warning"
          message={message}
        />
      </Snackbar>
    );
  }
}

export default AppNotFound;

1 个答案:

答案 0 :(得分:1)

我认为实现您想要的目标的好方法是添加另一个状态属性“ snackBarOpen”,这将帮助您确定用户是否输入了空值或有意义的东西:

AppSearchBarInput组件

state = {
  appId: '',
  snackBarOpen: false
}

handleKeyDown = (e) => {
  if (e.keyCode === 13 && e.target.value === '') {
    this.setState({
      appId: e.target.value,
      snackBarOpen: true
    });
  } else {
    this.setState({
      appId: e.target.value
    })
  }
}

handleCloseSnackBar = () => {
  this.setState({
    snackBarOpen: false
  });
}

然后在render()方法中也渲染<AppNotFound />(默认情况下将被隐藏,因为它取决于打开的道具):

render() {
  const { snackBarOpen } = this.state;

  return(
    <div>
      /* <InputBase /> here */
      <AppNotFound message={/* Your message here */} open={snackBarOpen} onClose={this.handleCloseSnackBar} />
    </div>
  )      
}

AppNotFound组件

您现在可以删除所有方法,仅保留render()一种方法,该方法将在接下来出现:

render() {
  const { message, open, onClose } = this.props;
  return (
    <Snackbar
      // ...
      open={open}
      // ...
      onClose={onClose}
    >
      <SnackbarMessage
        onClose={onClose}
        // ...
        message={message}
      />
    </Snackbar>
  );
}

希望我的回答会有用:)