Как отобразить снэк-бар условно на основе редукционного состояния с помощью thunks? - PullRequest
0 голосов
/ 26 ноября 2018

Я пишу веб-сайт в реагировании, который отображает информацию о мобильных приложениях, и я использую избыточность для хранения информации о текущем приложении.У меня есть текстовое поле ввода, расположенное в заголовке, где пользователь может ввести какой-либо идентификатор приложения, и, если это действительный идентификатор, они будут перенаправлены на другую страницу, если идентификатор недействителен, будет отображаться закусочная с соответствующим сообщением, и если пользователь только что нажал, введите «снэк-бар», также будет отображено соответствующее сообщение.AppNotFound - это компонент, который оборачивает снэк-бар.

Я использую избыточные избыточные значения для отправки действия, которое проверяет, действителен ли идентификатор приложения (это асинхронная функция) внутри onKeyDown метода (getAppInfo),В идеале я хотел бы получить результат от редукса уже в методе onKeyDown.Но поскольку действие отправляется асинхронно, я не могу.

Поэтому я подумал, чтобы render отобразил снэк-бар в зависимости от значения свойства found (было найдено приложение или нет).Таким образом, сначала found будет undefined, потому что асинхронная отправка не вернет результат в render, но тогда found станет true или false, и тогда мы сможем отобразить снэк-бар.Визуализация будет вызвана автоматически во второй раз, потому что реквизиты изменились.Но этого не происходит.

Как правильно с точки зрения шаблонов достичь того, чего я хочу?Я не хочу использовать componentWillReceiveProps как устаревший.

Это мой код:

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';

import * as log from 'loglevel';
log.setLevel("debug")


class AppSearchBarInput extends Component {
  state = {
    appId: '',
    snackBarOpen: false
  }

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

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

    if (e.keyCode === constants.ENTER_KEY) {

      this.props.getAppInfo({ appId });
      if (found) {
        this.props.history.push('/moreInfo');
      } else {
        this.setState({
          snackBarOpen: true
        });
      }

      this.setState({
        appId: ''
      });
    }
  }

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

  render() {

    const { classes, app } = this.props;
    const { snackBarOpen } = this.state;
    const { found, appId } = app;
    let message = '';

    if (!found) {
      message = appId === '' ? constants.MESSAGES.APP_BLANK() : constants.MESSAGES.APP_NOT_FOUND(appId);
    }

    let displayWhenFoundIsUndefined = null;

    if (found === undefined) {
      displayWhenFoundIsUndefined = <div>Loading...</div>;
    } else {
      displayWhenFoundIsUndefined = <AppNotFound message={message}
                   open={!found}
                   onClose={this.handleCloseSnackBar}/>;
    }
    return (
      <div>
        <InputBase
          placeholder="Search…"
          classes={{
            root: classes.inputRoot,
            input: classes.inputInput,
          }}
          onChange={this.onChange}
          onKeyDown={this.onKeyDown}
          value={this.state.appId} />
        {displayWhenFoundIsUndefined}
      </div>
    )
  }
}

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

const mapStateToProps = state => ({
  app: state.app.app
});

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

1 Ответ

0 голосов
/ 30 ноября 2018

Поскольку никто до сих пор не ответил на этот вопрос, я предложу решение, к которому недавно пришел.

Проблема, по сути, заключается в том, что отображение AppSearchBarInput зависит главным образом от того, было ли найдено приложениеили нет.Это действие должно быть асинхронным, поскольку информация поступает из Web API.Поэтому я использовал redux-thunk s и получал информацию о мобильном приложении в реквизите.Однако свойство snackbarOpen находилось в состоянии, что является проблемой, потому что снэк-бар зависит от свойства состояния, которое само по себе зависит от реквизита, получаемого асинхронно.

Решение этой проблемы состоит в том, чтобы переместить snackbarOpen вреквизит также.Поэтому теперь действие по установке snackbarOpen на true следует отправлять непосредственно из getAppInfo thunk, если приложение не было найдено, а также из onKeyDown, когда приложение пустое.С другой стороны, действие для установки snackbarOpen в false должно отправляться из handleCloseSnackBar.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...