如何使用 thunks 根据 redux 状态有条件地显示小吃店?
How to display a snackbar conditionally based on redux state using thunks?
我正在用 React 编写一个显示移动应用程序信息的网站,我正在使用 redux 来存储有关当前应用程序的信息。我有一个位于 header 的输入文本字段,用户可以在其中输入一些应用程序 ID,如果它是一个有效的 ID,他们将被重定向到另一个页面,如果该 ID 无效,则 snackbar 将显示适当的消息,如果用户只是点击回车,小吃店也将显示适当的消息。 AppNotFound
是包装 snackbar 的组件。
我在 onKeyDown
方法 (getAppInfo
) 中使用 redux thunks 来分派一个动作来检查应用程序 ID 是否有效(它是一个异步函数)。理想情况下,我想从已经在 onKeyDown
方法中的 redux 中获得结果。但是因为动作是异步调度的,所以我不能。
所以我想让 render
根据 found
属性 的值(无论是否找到应用程序)来显示一个 snackbar。所以起初 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);
既然没有人回答这个问题,我将提供我最近得到的解决方案。
问题本质上是 AppSearchBarInput
的显示主要取决于是否找到该应用程序。此操作必须是异步的,因为信息来自 Web API。因此,我正在使用 redux-thunk
s 并在 props 中接收移动应用程序信息。然而 snackbarOpen
属性 处于一个问题状态,因为小吃店依赖于状态 属性,而状态本身依赖于异步接收的道具。
解决困境的方法是snackbarOpen
也移动到道具上。因此,如果未找到该应用程序,那么现在应将 snackbarOpen
设置为 true
的操作直接从 getAppInfo
thunk 发送,如果应用程序为空,则应从 onKeyDown
发送。另一方面,将 snackbarOpen
设置为 false 的操作应该从 handleCloseSnackBar
发送。
我正在用 React 编写一个显示移动应用程序信息的网站,我正在使用 redux 来存储有关当前应用程序的信息。我有一个位于 header 的输入文本字段,用户可以在其中输入一些应用程序 ID,如果它是一个有效的 ID,他们将被重定向到另一个页面,如果该 ID 无效,则 snackbar 将显示适当的消息,如果用户只是点击回车,小吃店也将显示适当的消息。 AppNotFound
是包装 snackbar 的组件。
我在 onKeyDown
方法 (getAppInfo
) 中使用 redux thunks 来分派一个动作来检查应用程序 ID 是否有效(它是一个异步函数)。理想情况下,我想从已经在 onKeyDown
方法中的 redux 中获得结果。但是因为动作是异步调度的,所以我不能。
所以我想让 render
根据 found
属性 的值(无论是否找到应用程序)来显示一个 snackbar。所以起初 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);
既然没有人回答这个问题,我将提供我最近得到的解决方案。
问题本质上是 AppSearchBarInput
的显示主要取决于是否找到该应用程序。此操作必须是异步的,因为信息来自 Web API。因此,我正在使用 redux-thunk
s 并在 props 中接收移动应用程序信息。然而 snackbarOpen
属性 处于一个问题状态,因为小吃店依赖于状态 属性,而状态本身依赖于异步接收的道具。
解决困境的方法是snackbarOpen
也移动到道具上。因此,如果未找到该应用程序,那么现在应将 snackbarOpen
设置为 true
的操作直接从 getAppInfo
thunk 发送,如果应用程序为空,则应从 onKeyDown
发送。另一方面,将 snackbarOpen
设置为 false 的操作应该从 handleCloseSnackBar
发送。