I'm having an issue with a React Native application that uses Redux, and I've struggling to figure out the cause.
When the Redux state is changed by a dispatch in component A, component B doesn't show the most up to date value of the Redux state. For example, say I click a button in component A to change a Redux value from 0 to 1, it will show 0 in component B, but when I click the button to add 1 to make it 2, component B will show 1. Below is an example of my code. When I click on the TouchableOpacity in component A, it should change this.props.screen from 1 (the initial state) to 0. In component B, I have a regular console.log of this.props.screen, and a console.log inside a setTimeout with 50 milliseconds. Inside the console, the console.log in the setTimeout has the correct value of 0 when hit, however the one outside it still shows 1. Similarly, the text rendered in component B will show 1 as well. If I click the button again, it will then show 0.
I've included the relevant action and reducer from my code. At first, I thought it might be a mutation, but it seemed that can only happen with objects and arrays (I'm only using a number). I would appreciate some help figuring out how to have the text rendered in component B reflect the most current value. Thanks in advance!
Component A
import { connect } from "react-redux";
import { setScreen } from "../redux/Actions";
class Header extends Component {
componentWillReceiveProps(nextProps){
setTimeout(() => { this.logoHide() },10);
this.props.scrollLocation < 10 ? this.changeTransparency(0) : this.changeTransparency(.9);
}
setScreen(screen){
this.props.setScreen(screen);
}
render() {
var {height, width} = Dimensions.get('window');
return (
<View>
<TouchableOpacity onPress={() => this.setScreen(0)}>
<Text>Click Me</Text>
</TouchableOpacity>
</View>
);
}
}
const mapStateToProps = state => {
return {
height: state.height,
platform: state.platform,
screen: state.screen,
scrollLocation: state.scrollLocation
};
};
const mapDispatchToProps = dispatch => {
return {
setScreen: (value) => dispatch(setScreen(value))
};
};
export default connect(mapStateToProps,mapDispatchToProps)(Header);
Redux Action
import { SET_SCREEN } from './Constants';
export const setScreenDispatcher = (value) => ({ type: SET_SCREEN, screen: value});
export const setScreen = (value) => {
return (dispatch) => {
dispatch(setScreenDispatcher(value));
}
}
Redux Reducer
import { combineReducers } from 'redux';
import { SET_SCREEN } from "./Constants";
const initialState = []
const screen = (state = 1, action) => {
switch (action.type) {
case SET_SCREEN:
return action.screen;
default:
return state;
}
};
// COMBINE REDUCERS //
export default combineReducers({
screen
});
Component B
import { connect } from "react-redux";
class VisibleMenus extends Component {
componentWillUpdate(){
console.log(this.props.screen);
setTimeout(() => {console.log(this.props.screen)},50);
}
}
render() {
return (
<View>
<Text>{this.props.screen}</Text>
</View>
);
}
}
const mapStateToProps = state => {
return {
screen: state.screen
};
};
const mapDispatchToProps = dispatch => {
return {
};
};
export default connect(mapStateToProps,mapDispatchToProps)(VisibleMenus);
App.js
import React, {Component} from 'react';
import { Provider } from "react-redux";
import VisibleMenus from './VisibleMenus';
import { Store } from "./redux/Store";
const store = Store();
export default class App extends Component {
render() {
return (
<Provider store={store}>
<VisibleMenus />
</Provider>
);
}
}
Store.js
// REDUX STORE //
import { createStore, applyMiddleware } from "redux";
import rootReducer from "./Reducers";
import ReduxThunk from 'redux-thunk'
export const Store = (initialState) => {
return createStore(
rootReducer,
initialState,
applyMiddleware(ReduxThunk)
);
}