How to set react state with new props immediately after calling `dispatch` via react-redux connect?
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);
javascript reactjs redux react-redux
add a comment |
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);
javascript reactjs redux react-redux
There's nodispatch
in the code you posted. Please, update it to clarify where it should be. I could use componentDidUpdate but then I can't update local store from it - why?
– estus
Nov 20 at 22:08
UsingcomponentWillReceiveProps
solved my problem but it's still not the recommended method to use, though.
– hitchhiker
Nov 21 at 21:05
add a comment |
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);
javascript reactjs redux react-redux
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);
javascript reactjs redux react-redux
javascript reactjs redux react-redux
edited Nov 21 at 5:19
asked Nov 20 at 21:18
hitchhiker
727
727
There's nodispatch
in the code you posted. Please, update it to clarify where it should be. I could use componentDidUpdate but then I can't update local store from it - why?
– estus
Nov 20 at 22:08
UsingcomponentWillReceiveProps
solved my problem but it's still not the recommended method to use, though.
– hitchhiker
Nov 21 at 21:05
add a comment |
There's nodispatch
in the code you posted. Please, update it to clarify where it should be. I could use componentDidUpdate but then I can't update local store from it - why?
– estus
Nov 20 at 22:08
UsingcomponentWillReceiveProps
solved my problem but it's still not the recommended method to use, though.
– hitchhiker
Nov 21 at 21:05
There's no
dispatch
in the code you posted. Please, update it to clarify where it should be. I could use componentDidUpdate but then I can't update local store from it - why?– estus
Nov 20 at 22:08
There's no
dispatch
in the code you posted. Please, update it to clarify where it should be. I could use componentDidUpdate but then I can't update local store from it - why?– estus
Nov 20 at 22:08
Using
componentWillReceiveProps
solved my problem but it's still not the recommended method to use, though.– hitchhiker
Nov 21 at 21:05
Using
componentWillReceiveProps
solved my problem but it's still not the recommended method to use, though.– hitchhiker
Nov 21 at 21:05
add a comment |
1 Answer
1
active
oldest
votes
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
Although you may have a point regardingwithRouter
this is not the problem I was to referring to. Changing the order ofconnect
andwithRouter
didn't make the problem go away. I do havedispatch
method insidegetAppInfo
. The problem is that the prop update will only be available after the next tick: github.com/reduxjs/react-redux/issues/…
– hitchhiker
Nov 21 at 19:27
@hitchhiker if I understand you, you're trying to synchronously get updated state as props within the function that dispatched global state update? Please correct me if I'm wrong. That's indeed an anti-pattern. You really should consider usingcomponentWillReceiveProps
orcomponentDidUpdate
. I once made a lil project in the past that helps demonstrate a way to work around this. In the project UI is instantly updated after light calculations on window resize. Please tell me if it helps you and I'll update my answer. Find it here: codesandbox.io/s/233yq699yr
– Caleb Lucas
Nov 21 at 21:24
@hitchhiker However, if you need to update store immediately, then you really should consider using another middleware. There'sredux-saga
andredux-observable
. I can speak highly ofredux-saga
because of the way it handles action dispatch and general function calls. It is also very advantageous for testing because it uses generator functions and an object representation of every function call. If you were usingsaga
, then what you want to do would be straightforward with ayield put
and then ayield call
– Caleb Lucas
Nov 21 at 21:32
" if I understand you, you're trying to synchronously get updated state as props within the function that dispatched global state update" - Yes. HowevercomponentWillReceiveProps
is now a legacy method and its use is discouraged. I don't want to use other libraries like the ones you mentioned. I think memoization is a technique that can be used here?
– hitchhiker
Nov 21 at 21:37
Is there a reason why you don't want to use the libraries? For react design patterns they are one of the best. I mean, whether a small or large project. Memoization? Hmmnn.. would be interesting to see how that could be applied to your specific situation.
– Caleb Lucas
Nov 21 at 21:39
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53401670%2fhow-to-set-react-state-with-new-props-immediately-after-calling-dispatch-via-r%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
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
Although you may have a point regardingwithRouter
this is not the problem I was to referring to. Changing the order ofconnect
andwithRouter
didn't make the problem go away. I do havedispatch
method insidegetAppInfo
. The problem is that the prop update will only be available after the next tick: github.com/reduxjs/react-redux/issues/…
– hitchhiker
Nov 21 at 19:27
@hitchhiker if I understand you, you're trying to synchronously get updated state as props within the function that dispatched global state update? Please correct me if I'm wrong. That's indeed an anti-pattern. You really should consider usingcomponentWillReceiveProps
orcomponentDidUpdate
. I once made a lil project in the past that helps demonstrate a way to work around this. In the project UI is instantly updated after light calculations on window resize. Please tell me if it helps you and I'll update my answer. Find it here: codesandbox.io/s/233yq699yr
– Caleb Lucas
Nov 21 at 21:24
@hitchhiker However, if you need to update store immediately, then you really should consider using another middleware. There'sredux-saga
andredux-observable
. I can speak highly ofredux-saga
because of the way it handles action dispatch and general function calls. It is also very advantageous for testing because it uses generator functions and an object representation of every function call. If you were usingsaga
, then what you want to do would be straightforward with ayield put
and then ayield call
– Caleb Lucas
Nov 21 at 21:32
" if I understand you, you're trying to synchronously get updated state as props within the function that dispatched global state update" - Yes. HowevercomponentWillReceiveProps
is now a legacy method and its use is discouraged. I don't want to use other libraries like the ones you mentioned. I think memoization is a technique that can be used here?
– hitchhiker
Nov 21 at 21:37
Is there a reason why you don't want to use the libraries? For react design patterns they are one of the best. I mean, whether a small or large project. Memoization? Hmmnn.. would be interesting to see how that could be applied to your specific situation.
– Caleb Lucas
Nov 21 at 21:39
add a comment |
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
Although you may have a point regardingwithRouter
this is not the problem I was to referring to. Changing the order ofconnect
andwithRouter
didn't make the problem go away. I do havedispatch
method insidegetAppInfo
. The problem is that the prop update will only be available after the next tick: github.com/reduxjs/react-redux/issues/…
– hitchhiker
Nov 21 at 19:27
@hitchhiker if I understand you, you're trying to synchronously get updated state as props within the function that dispatched global state update? Please correct me if I'm wrong. That's indeed an anti-pattern. You really should consider usingcomponentWillReceiveProps
orcomponentDidUpdate
. I once made a lil project in the past that helps demonstrate a way to work around this. In the project UI is instantly updated after light calculations on window resize. Please tell me if it helps you and I'll update my answer. Find it here: codesandbox.io/s/233yq699yr
– Caleb Lucas
Nov 21 at 21:24
@hitchhiker However, if you need to update store immediately, then you really should consider using another middleware. There'sredux-saga
andredux-observable
. I can speak highly ofredux-saga
because of the way it handles action dispatch and general function calls. It is also very advantageous for testing because it uses generator functions and an object representation of every function call. If you were usingsaga
, then what you want to do would be straightforward with ayield put
and then ayield call
– Caleb Lucas
Nov 21 at 21:32
" if I understand you, you're trying to synchronously get updated state as props within the function that dispatched global state update" - Yes. HowevercomponentWillReceiveProps
is now a legacy method and its use is discouraged. I don't want to use other libraries like the ones you mentioned. I think memoization is a technique that can be used here?
– hitchhiker
Nov 21 at 21:37
Is there a reason why you don't want to use the libraries? For react design patterns they are one of the best. I mean, whether a small or large project. Memoization? Hmmnn.. would be interesting to see how that could be applied to your specific situation.
– Caleb Lucas
Nov 21 at 21:39
add a comment |
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
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
edited Nov 20 at 22:24
answered Nov 20 at 22:19
Caleb Lucas
665
665
Although you may have a point regardingwithRouter
this is not the problem I was to referring to. Changing the order ofconnect
andwithRouter
didn't make the problem go away. I do havedispatch
method insidegetAppInfo
. The problem is that the prop update will only be available after the next tick: github.com/reduxjs/react-redux/issues/…
– hitchhiker
Nov 21 at 19:27
@hitchhiker if I understand you, you're trying to synchronously get updated state as props within the function that dispatched global state update? Please correct me if I'm wrong. That's indeed an anti-pattern. You really should consider usingcomponentWillReceiveProps
orcomponentDidUpdate
. I once made a lil project in the past that helps demonstrate a way to work around this. In the project UI is instantly updated after light calculations on window resize. Please tell me if it helps you and I'll update my answer. Find it here: codesandbox.io/s/233yq699yr
– Caleb Lucas
Nov 21 at 21:24
@hitchhiker However, if you need to update store immediately, then you really should consider using another middleware. There'sredux-saga
andredux-observable
. I can speak highly ofredux-saga
because of the way it handles action dispatch and general function calls. It is also very advantageous for testing because it uses generator functions and an object representation of every function call. If you were usingsaga
, then what you want to do would be straightforward with ayield put
and then ayield call
– Caleb Lucas
Nov 21 at 21:32
" if I understand you, you're trying to synchronously get updated state as props within the function that dispatched global state update" - Yes. HowevercomponentWillReceiveProps
is now a legacy method and its use is discouraged. I don't want to use other libraries like the ones you mentioned. I think memoization is a technique that can be used here?
– hitchhiker
Nov 21 at 21:37
Is there a reason why you don't want to use the libraries? For react design patterns they are one of the best. I mean, whether a small or large project. Memoization? Hmmnn.. would be interesting to see how that could be applied to your specific situation.
– Caleb Lucas
Nov 21 at 21:39
add a comment |
Although you may have a point regardingwithRouter
this is not the problem I was to referring to. Changing the order ofconnect
andwithRouter
didn't make the problem go away. I do havedispatch
method insidegetAppInfo
. The problem is that the prop update will only be available after the next tick: github.com/reduxjs/react-redux/issues/…
– hitchhiker
Nov 21 at 19:27
@hitchhiker if I understand you, you're trying to synchronously get updated state as props within the function that dispatched global state update? Please correct me if I'm wrong. That's indeed an anti-pattern. You really should consider usingcomponentWillReceiveProps
orcomponentDidUpdate
. I once made a lil project in the past that helps demonstrate a way to work around this. In the project UI is instantly updated after light calculations on window resize. Please tell me if it helps you and I'll update my answer. Find it here: codesandbox.io/s/233yq699yr
– Caleb Lucas
Nov 21 at 21:24
@hitchhiker However, if you need to update store immediately, then you really should consider using another middleware. There'sredux-saga
andredux-observable
. I can speak highly ofredux-saga
because of the way it handles action dispatch and general function calls. It is also very advantageous for testing because it uses generator functions and an object representation of every function call. If you were usingsaga
, then what you want to do would be straightforward with ayield put
and then ayield call
– Caleb Lucas
Nov 21 at 21:32
" if I understand you, you're trying to synchronously get updated state as props within the function that dispatched global state update" - Yes. HowevercomponentWillReceiveProps
is now a legacy method and its use is discouraged. I don't want to use other libraries like the ones you mentioned. I think memoization is a technique that can be used here?
– hitchhiker
Nov 21 at 21:37
Is there a reason why you don't want to use the libraries? For react design patterns they are one of the best. I mean, whether a small or large project. Memoization? Hmmnn.. would be interesting to see how that could be applied to your specific situation.
– Caleb Lucas
Nov 21 at 21:39
Although you may have a point regarding
withRouter
this is not the problem I was to referring to. Changing the order of connect
and withRouter
didn't make the problem go away. I do have dispatch
method inside getAppInfo
. The problem is that the prop update will only be available after the next tick: github.com/reduxjs/react-redux/issues/…– hitchhiker
Nov 21 at 19:27
Although you may have a point regarding
withRouter
this is not the problem I was to referring to. Changing the order of connect
and withRouter
didn't make the problem go away. I do have dispatch
method inside getAppInfo
. The problem is that the prop update will only be available after the next tick: github.com/reduxjs/react-redux/issues/…– hitchhiker
Nov 21 at 19:27
@hitchhiker if I understand you, you're trying to synchronously get updated state as props within the function that dispatched global state update? Please correct me if I'm wrong. That's indeed an anti-pattern. You really should consider using
componentWillReceiveProps
or componentDidUpdate
. I once made a lil project in the past that helps demonstrate a way to work around this. In the project UI is instantly updated after light calculations on window resize. Please tell me if it helps you and I'll update my answer. Find it here: codesandbox.io/s/233yq699yr– Caleb Lucas
Nov 21 at 21:24
@hitchhiker if I understand you, you're trying to synchronously get updated state as props within the function that dispatched global state update? Please correct me if I'm wrong. That's indeed an anti-pattern. You really should consider using
componentWillReceiveProps
or componentDidUpdate
. I once made a lil project in the past that helps demonstrate a way to work around this. In the project UI is instantly updated after light calculations on window resize. Please tell me if it helps you and I'll update my answer. Find it here: codesandbox.io/s/233yq699yr– Caleb Lucas
Nov 21 at 21:24
@hitchhiker However, if you need to update store immediately, then you really should consider using another middleware. There's
redux-saga
and redux-observable
. I can speak highly of redux-saga
because of the way it handles action dispatch and general function calls. It is also very advantageous for testing because it uses generator functions and an object representation of every function call. If you were using saga
, then what you want to do would be straightforward with a yield put
and then a yield call
– Caleb Lucas
Nov 21 at 21:32
@hitchhiker However, if you need to update store immediately, then you really should consider using another middleware. There's
redux-saga
and redux-observable
. I can speak highly of redux-saga
because of the way it handles action dispatch and general function calls. It is also very advantageous for testing because it uses generator functions and an object representation of every function call. If you were using saga
, then what you want to do would be straightforward with a yield put
and then a yield call
– Caleb Lucas
Nov 21 at 21:32
" if I understand you, you're trying to synchronously get updated state as props within the function that dispatched global state update" - Yes. However
componentWillReceiveProps
is now a legacy method and its use is discouraged. I don't want to use other libraries like the ones you mentioned. I think memoization is a technique that can be used here?– hitchhiker
Nov 21 at 21:37
" if I understand you, you're trying to synchronously get updated state as props within the function that dispatched global state update" - Yes. However
componentWillReceiveProps
is now a legacy method and its use is discouraged. I don't want to use other libraries like the ones you mentioned. I think memoization is a technique that can be used here?– hitchhiker
Nov 21 at 21:37
Is there a reason why you don't want to use the libraries? For react design patterns they are one of the best. I mean, whether a small or large project. Memoization? Hmmnn.. would be interesting to see how that could be applied to your specific situation.
– Caleb Lucas
Nov 21 at 21:39
Is there a reason why you don't want to use the libraries? For react design patterns they are one of the best. I mean, whether a small or large project. Memoization? Hmmnn.. would be interesting to see how that could be applied to your specific situation.
– Caleb Lucas
Nov 21 at 21:39
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53401670%2fhow-to-set-react-state-with-new-props-immediately-after-calling-dispatch-via-r%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
There's no
dispatch
in the code you posted. Please, update it to clarify where it should be. I could use componentDidUpdate but then I can't update local store from it - why?– estus
Nov 20 at 22:08
Using
componentWillReceiveProps
solved my problem but it's still not the recommended method to use, though.– hitchhiker
Nov 21 at 21:05