【问题标题】:How to combine Material-UI's snackbar and input components in react?react中如何结合Material-UI的snackbar和input组件?
【发布时间】:2023-03-14 12:22:01
【问题描述】:

我正在使用Material-UI 组件来构建我的网站。我有一个带有搜索字段的标题组件,它在引擎盖下使用 mui InputBase。当用户输入空输入时(即他们不输入任何内容,只需单击输入),我想显示一个 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;

【问题讨论】:

    标签: javascript reactjs design-patterns material-ui


    【解决方案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() 方法中也渲染&lt;AppNotFound /&gt;(默认情况下它会被隐藏,因为它依赖于 open prop):

    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>
      );
    }
    

    希望我的回答对你有用:)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-08-11
      • 1970-01-01
      • 2020-01-19
      • 2020-10-08
      • 2016-11-06
      • 1970-01-01
      • 2018-06-06
      • 2020-07-09
      相关资源
      最近更新 更多