Reputation: 301
I am writing a React Native app and using Redux.
I have followed this tutorial.
I have faced with the following warning message:
Warning: Cannot update during an existing state transition (such as within 'render' or another component's constructor). Render methods should be a pure function of props and state; constructor side-effects are an anti-pattern, but can be moved to 'componentWillMount'
Here is what I have:
MyComponent.js
import React from 'react';
import { login } from './actions'
import { connect } from 'react-redux';
import { View, Text } from 'react-native';
import { Button } from 'native-base';
class MyComponent extends React.Component {
render() {
return(
<View>
<Button onPress={() => this.props.login("username","password")}>
<Text>
Login!
<Text>
</Button>
</View>
)
}
}
function mapStateToProps(state) {
return { state: state.login }
}
function mapDispatchToProps(dispatch) {
return {
login: (username, password) => dispatch(login(username, password))
}
}
export default connect(mapStateToProps, mapDispatchToProps)(LoginScreen);
App.js
import React, { Component } from 'react';
import MyComponent from './MyComponent';
import { Provider } from 'react-redux';
import configureStore from './configureStore';
import Route from './config/Router';
export default class App extends Component {
render() {
let store = configureStore();
return (
<Provider store={store}>
<MyComponent />
</Provider>
);
}
}
configureStore.js
import { createStore } from 'redux';
import reducers from './reducers';
import thunk from 'redux-thunk';
export default function configureStore() {
let store = createStore(reducers, applyMiddleware(thunk));
return store;
}
reducers.js
import * from './constants'
import { combineReducers } from 'redux';
const initialState = {
isLoggedIn: false,
isLoggingIn: false,
username: '',
error: false
};
function loginReducer(state = initialState, action) {
console.log('Reducer is called.');
console.log('Action is ' + JSON.stringify(action));
console.log('state is ' + JSON.stringify(state));
switch (action.type) {
case LOGGING_IN:
return {
...state,
isLoggedIn: false,
isLoggingIn: true,
username: '',
error: false
}
case LOG_IN_SUCCESS:
return {
...state,
isLoggedIn: true,
isLoggingIn: false,
username: action.data.username,
error: false
}
case LOG_IN_FAILURE:
return {
...state,
isLoggedIn: false,
isLoggingIn: false,
username: '',
error: true
}
}
}
export default rootReducer = combineReducers({
loginReducer,
});
actions.js
import * './constants'
import { Actions } from 'react-native-router-flux';
export function login(username, password) {
return (dispatch) => {
dispatch(loggingIn())
//here will be some API ASYNC CALLS!
//depending on the result we will dispatch again!
myService.login(username,password).done((result) => {
if(result !== null) {
dispatch(loginSuccess(result))
} else {
dispatch(loginFailure())
}
})
}
}
function loggingIn() {
return {
type: LOGGING_IN
}
}
function loginSuccess(data) {
return {
type: LOG_IN_SUCCESS,
data: data
}
}
function loginFailure() {
return {
type: LOG_IN_FAILURE
}
}
I have debugged the code. I have seen that the warning comes right after first dispatch call! ( dispatch(loggingIn()) )
So, I don't know what the problem is.
I also wonder if this is the true use of redux and async api calls. Can you help me? Thanks a lot.
Upvotes: 1
Views: 4355
Reputation: 9185
As far as I recall from my experience, this error usually appears when you are trying to update something in your render method, which is prohibited.
Verify that it is not happening in your app.
UPD: Try creating a function above the render method that calls this.props.login instead of doing it inside mapDispatchToProps. And add your the login action creator instead of mapDispatchToProps as a second argument to the connect function.
Upvotes: 1
Reputation: 2220
I think something wrong here
function mapStateToProps(state) {
return { state: state.login }
}
Should be
function mapStateToProps(state) {
return { loginReducer: state.loginReducer }
}
Upvotes: 2