Я пишу веб-сайт в реагировании, который отображает информацию о мобильных приложениях, и я использую избыточность для хранения информации о текущем приложении.У меня есть текстовое поле ввода, расположенное в заголовке, где пользователь может ввести какой-либо идентификатор приложения, и, если это действительный идентификатор, они будут перенаправлены на другую страницу, если идентификатор недействителен, будет отображаться закусочная с соответствующим сообщением, и если пользователь только что нажал, введите «снэк-бар», также будет отображено соответствующее сообщение.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);