Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React Native + Redux: Why does Switch immediately turns back to false after being switched to true?

In iOS React Native + Redux, I am using the following Switch component (https://facebook.github.io/react-native/docs/switch.html). It is first set as off, but then when switched on, it immediately switches off by itself. What may be the issue?

This is my set up:

<Switch
  onValueChange={this._handleSwitch}
  value={switch.currentValue}
/>

And the action triggered is:

  _handleSwitch(value) {
    this.props.actions.triggerSwitch(value)
  }

And the action is:

export function triggerSwitch(value) {
  return {
    type: TRIGGER_SWITCH,
    currentValue: value
  }
}

And in the reducer:

const initialState = {
  currentValue: false
}

function switchReducer(switch = initialState, action) {
  switch(action.type) {
    case TRIGGER_SWITCH:
      return {
        currentValue: action.currentValue
      }

     default:
       return switch
  }
}

export default switchReducer

Thank you!

like image 992
Jo Ko Avatar asked Aug 30 '16 08:08

Jo Ko


2 Answers

It is not because of redux, for Switch to work, we need to explicitly set the value from a state, otherwise it is set back to false immediately

<Switch
  value={this.state.hasRead}
  onValueChange={(value) => {
    this.setState({
      hasRead: value
    })
}} />
like image 81
onmyway133 Avatar answered Sep 23 '22 20:09

onmyway133


I tried to reproduce the described problem with redux and Switch, but the only issue I had is that switch is a reserved word, so I changed it to switchState. In case someone needs the working example:

js/actions/actionTypes.js

export const TRIGGER_SWITCH = 'TRIGGER_SWITCH';

js/actions/switchActions.js

import { TRIGGER_SWITCH } from './actionTypes';

export const triggerSwitch = value => ({
  type: TRIGGER_SWITCH,
  currentValue: value
});

js/reducers/switchReducer.js

import { TRIGGER_SWITCH } from '../actions/actionTypes';

const initialState = {
  currentValue: false
};

const switchReducer = (state = initialState, action) => {
  switch(action.type) {
    case TRIGGER_SWITCH:
      return {
        currentValue: action.currentValue
      };
    default:
      return state;
  }
};

export default switchReducer;

js/store.js

import {
  createStore,
  applyMiddleware,
  combineReducers
} from 'redux';
import { createLogger } from 'redux-logger';
import switchReducer from './reducers/switchReducer';

const logger = createLogger();

export default (initialState = {}) => (
  createStore(
    combineReducers({
      switchState: switchReducer
    }),
    initialState,
    applyMiddleware(logger)
  )
);

js/components/App.js

import React, { Component } from 'react';
import {
  StyleSheet,
  View,
  Switch
} from 'react-native';


export default class App extends Component {

  constructor(props) {
    super(props);

    this._handleSwitch = this._handleSwitch.bind(this);
  }

  _handleSwitch(value) {
    this.props.actions.triggerSwitch(value);
  }

  render() {
    const { switchState } = this.props;

    return (
      <View style={styles.container}>
        <Switch
          onValueChange={this._handleSwitch}
          value={switchState.currentValue}
        />
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
  },
});

js/containers/App.js

import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import { triggerSwitch } from '../actions/switchActions';
import App from '../components/App';

const mapStateToProps = state => ({
  switchState: state.switchState
});

const mapDispatchToProps = dispatch => ({
  actions: bindActionCreators({
    triggerSwitch
  }, dispatch)
});

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(App);

index.ios.js

import React, { Component } from 'react';
import { AppRegistry } from 'react-native';
import { Provider } from 'react-redux';
import createStore from './js/store';
import App from './js/containers/App';

const store = createStore();


const SwitchTest = () => (
  <Provider store={store}>
    <App />
  </Provider>
);

AppRegistry.registerComponent('SwitchTest', () => SwitchTest);

export default SwitchTest;

package.json dependencies

"dependencies": {
    "react": "16.0.0-alpha.12",
    "react-native": "0.46.4",
    "react-redux": "^5.0.5",
    "redux": "^3.7.2",
    "redux-logger": "^3.0.6"
},
like image 36
mihai1990 Avatar answered Sep 24 '22 20:09

mihai1990