I'm new to React and Redux and I'm trying to build a website. I'm using Material-UI components. The AppSearchBarInput
is an input in the header where users can search for an id (referred to as appId
in the code). If appId
is found
in the database then I want to redirect to another page ( this.props.history.push('/app/appInfo');
). If the input is blank then I display a snackbar ( AppNotFound
) with warning message as well as when the input doesn't exist in the database.
In the onKeyDown
method I use connect
to dispatch an action which checks if the id exists in the database ( dispatch
is called from getAppInfo
using redux-thunk
). Then I need to immediately get the new Redux state via props in order to decide whether the id was found or not and depending on this I set snackBarOpen
local state property to true or false.
The problem is that I can't get the updated props within the same method when calling dispatch. I could use componentDidUpdate
but then I can't update local store from it. Is there some workaround for this situation either using some react lifecycle method or redux trick?
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;
if (e.keyCode === constants.ENTER_KEY) {
if (appId.trim() !== '') {
this.props.getAppInfo({ appId });
this.setState({
appId: ''
});
const { found } = this.props.app; // ! problem here !
if (found) {
this.props.history.push('/app/appInfo');
} else {
this.setState({
snackBarOpen: true
});
}
} else {
this.setState({
snackBarOpen: true
});
}
}
}
handleCloseSnackBar = () => {
this.setState({
snackBarOpen: false
});
}
render() {
const { classes } = this.props;
const { appId, snackBarOpen } = this.state;
const { found } = this.props.app;
let message = '';
if (!found) {
message = appId === '' ? constants.MESSAGES.APP_BLANK() : constants.MESSAGES.APP_NOT_FOUND(appId);
}
return (
<div>
<InputBase
placeholder="Search…"
classes={{
root: classes.inputRoot,
input: classes.inputInput,
}}
onChange={this.onChange}
onKeyDown={this.onKeyDown}
value={this.state.appId} />
<AppNotFound message={message}
open={snackBarOpen && !found}
onClose={this.handleCloseSnackBar}/>
</div>
)
}
}
AppSearchBarInput.propTypes = {
classes: PropTypes.object.isRequired
}
const mapStateToProps = state => ({
app: state.app.app
});
const AppSearchBarWithStyles = withStyles(AppSearchBarInputStyles)(AppSearchBarInput);
const AppSearchBarWithStylesWithRouter = withRouter(AppSearchBarWithStyles);
export default connect(mapStateToProps, { getAppInfo })(AppSearchBarWithStylesWithRouter);
From the look of your code you have no dispatch method. If data was really fetched, then you're not getting updates because withRouter
actually blocks shouldComponentUpdate. If you want updated state, wrap the connect
in withRouter
.
You should also have a mapDispatchToProps function. Like this:
const mapDispatchToProps = dispatch => ({
makeDispatch: () => dispatch({ getAppInfo })
})
So, instead of:
const AppSearchBarWithStyles = withStyles(AppSearchBarInputStyles)(AppSearchBarInput);
const AppSearchBarWithStylesWithRouter = withRouter(AppSearchBarWithStyles);
export default connect(mapStateToProps, { getAppInfo })(AppSearchBarWithStylesWithRouter);
You should have:
const AppSearchBarWithStyles = withStyles(AppSearchBarInputStyles)(AppSearchBarInput);
AppSearchBarWithStylesWithConnect = connect(mapStateToProps, mapDispatchToProps)(AppSearchBarWithStyles);
export default withRouter(AppSearchBarWithStylesWithConnect);
Please see this: https://reacttraining.com/react-router/core/api/withRouter
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.