Kaidao Kaidao - 3 months ago 53
React JSX Question

React Native / Redux - setState - Cannot update during an existing state transition

I'm building an app using React Native and Redux and have come across a problem during implementation. I'm receiving an error that says


setState cannot update during an existing state transition (such as
within render or another component's constructor).


When I load the app simulator, it seems to trigger handleLogin() right away (and on a loop) before any user input.

Here's the
AuthenticationContainer
and the
AuthenticationPage
code:

AuthenticationContainer.js:


'use strict'

import React, { Component, PropTypes } from 'react';
import AuthenticatePage from '../../components/Authenticate/AuthenticatePage'
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux'
import * as sessionActionCreators from '../../redux/session';
import {Actions, ActionConst} from 'react-native-router-flux'

class AuthenticateContainer extends Component {
constructor(props) {
super(props);
this.state = {
email: '',
password: ''
};
}

handleLogin() {
this.props.doLogin(this.state.email, this.state.password)
.then(() => Actions.tabbar())
}

render() {
return (
<AuthenticatePage
doLogin = {this.handleLogin.bind(this)}
error = {this.props.error}/>
);
}
}

AuthenticateContainer.propTypes = {
doLogin: PropTypes.func.isRequired,
email: PropTypes.string,
password: PropTypes.string,
error: PropTypes.string.isRequired
};

export default connect(
(state) => ({isFetching: state.session.isFetching, error: state.session.error}),
(dispatch) => bindActionCreators(sessionActionCreators, dispatch)
)(AuthenticateContainer)





AuthenticationPage.js



'use strict'

import React, { Component, PropTypes } from 'react';
import {Text, View, TouchableHighlight, AlertIOS} from 'react-native';
import t from 'tcomb-form-native'
import _ from 'lodash'
import EStyleSheet from 'react-native-extended-stylesheet'
import ViewContainer from '../ViewContainer'

// AuthenticatePage.propTypes = {
// doLogin: PropTypes.func.isRequired,
// onUpdateForm: PropTypes.func.isRequired,
// email: PropTypes.string,
// password: PropTypes.string,
// error: PropTypes.string.isRequired
// };

var Form = t.form.Form;

var User = t.struct({email: t.String, password: t.String});

const options = {
auto: 'placeholders',
fields: {
email: {
autoCapitalize: 'none',
autoCorrect: false
},

password: {
autoCapitalize: 'none',
autoCorrect: false,
password: true,
secureTextEntry: true
}
}
};

export default class AuthenticatePage extends Component {
constructor(props) {
super(props);
this.state = {
value: {
email: '',
password: ''
}
};
}

render() {
return (
<ViewContainer>
<View>
<Form
ref="form"
type={User}
options={options}
value={this.state.value}/>
</View>
<View>
<TouchableHighlight
onClick={this.props.doLogin()}
underlayColor='#99d9f4'>
<Text>{_.capitalize('Login')}</Text>
</TouchableHighlight>
</View>
</ViewContainer>
)
}
}





So the handleLogin() function seems to fire immediately on page load and will run repeatedly while throwing the error. Here's the error that I'm receiving from the simulator.

setState error

Any help would be greatly appreciated!

Answer

I believe the problem is here:

onClick={this.props.doLogin()}

You call a function on render, but you should be passing it as a prop instead. Either try to

onClick={() => this.props.doLogin()}

or

onClick={this.props.doLogin.bind(this)}

to fix.

Comments