2
votes

It's been 2 days that I'm stuck with an issue implementing redux in my react native application. I checked many topics but I can't fix my problem.

The problem is that mapStateToProps is called only once but it's not called anymore after executing action. My reducer is called but the state is not updating.

I test my work on android with android studio and emulator.

Here is my code :

App.js:

  <Provider store={createStore(reducers)}>
    <View>
         <MainScreen />
    </View>
  </Provider>

HeaderReducer:

export default (state = INITIAL_STATE, action) => {
  switch (action.type) {
    case SET_HEADER:
      return action.payload;
    default:
      return state;
 }

};

reducers/index.js

import { combineReducers } from 'redux';
import HeaderReducer from './HeaderReducer';

export default combineReducers({
  headerText: HeaderReducer,
});

actions/index.js

export const SET_HEADER = 'set_header';

export const setHeaderText = (title) => {
  return {
    type: SET_HEADER,
    payload: title,
  };
};

MainScreen.js

import * as actions from '../actions';

... 
<Text> {this.props.headerText} </Text>
<Button
          onPress={() => {
            this.props.setHeaderText(`screen: ${SELECTED_PAGE.profile}`);
            this.forceUpdate();
          }}
        >

 ...

const mapStateToProps = (state) => {
  const { headerText } = state;
  return { headerText };
};

export default connect(mapStateToProps, actions)(MainScreen);

I know that I don't need to forceUpdate in the onPress callback but it's just to check the state after call the function.

So when the application start the reducers are called and my mapStateToProps is working. But when I click on my button, my reducers are called, the good action is executed in the switch but my mapStateToProps is not called anymore. When I click a second time if I console.log the state in my reducer I can see that the state is not updated but stay the same than the INITIAL_STATE.

I don't mutate the state in my reducers, I connected everything in my MainScreen.js and I wrapped my app in Provider with store.

I follow a tutorial on Udemy to implement reduc in my app and even I check the code of the tuto on github, I can't find out where the issue is from (https://github.com/StephenGrider/ReactNativeReduxCasts/tree/master/tech_stack)

I think I miss something really obvious but I can't find out what's wrong since 2 days :/

If someone can help, I would appreciate :)

Thanks.

EDIT :

I didn't figure out the problem, so I just restart from scratch, I did exactly the same (THE SAAME!!) and it's working now... Thanks for your help :)

2
is App.js the entry of your app ? because i think that Provider must rendered at the top of the component tree. to make it simple, after creating your App.js, your index.js appears like (or no): ..... ReactDOM.render( <App />, document.getElementById('root') ); ...... And App is imported from your App.jsHsaido
Yes you're right, in my app.js I have AppRegistry.registerComponent(appName, () => App); and App is imported from my App.jsJulien Rousseau
I'm really confused!!! because i did the same as you in a sample project and it works well.Hsaido

2 Answers

1
votes

The problem is in your HeaderReducer, reducer is expecting to return a state object, but you're returning a string instead.

export default (state = INITIAL_STATE, action) => {
  switch (action.type) {
    case SET_HEADER:
      return action.payload;
    default:
      return state;
 }

During the case of SET_HEADER, what you really want is to overwrite a field instead of overwrite the whole state object, so change to below instead

const INITIAL_STATE = { customizeText: '' };

export default (state = INITIAL_STATE, action) => {
  switch (action.type) {
    case SET_HEADER:
      return { ...state, customizeText: action.payload }; // <<=== HERE
    default:
      return state;
  }
}

Then in your MainScreen.js, you have to update your mapStateToProps function

<Text> {this.props.someText} </Text>
...
const mapStateToProps = ({ headerText }) => {
  return { someText: headerText.customizeText };
};

...

I've updated the field name to avoid confusion

0
votes

First make an actual action as this.props.setHeaderText() and pass title if you wish to and make sure your INITIAL_STATE is an object or [].

const mapStateToProps = (state) => {
    return{ 
    headerText: state.headerText 
    }
    };
    export default connect(mapStateToProps, actions)(MainScreen);