在iOS React Native + Redux中,我使用以下Switch组件(https://facebook.github.io/react-native/docs/switch.html)。它首先设置为关闭,但是当打开时,它会立即自动关闭。可能是什么问题?
这是我的设置:
<Switch
onValueChange={this._handleSwitch}
value={switch.currentValue}
/>
触发的动作是:
_handleSwitch(value) {
this.props.actions.triggerSwitch(value)
}
行动是:
export function triggerSwitch(value) {
return {
type: TRIGGER_SWITCH,
currentValue: value
}
}
在减速器中:
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
谢谢!
答案 0 :(得分:2)
并不是因为存在冗余,Switch
才能正常工作,我们需要从状态显式设置value
,否则立即将其设置回false
<Switch
value={this.state.hasRead}
onValueChange={(value) => {
this.setState({
hasRead: value
})
}} />
答案 1 :(得分:1)
我尝试用redux和Switch重现所描述的问题,但我唯一的问题是switch是一个保留字,所以我将它改为switchState。如果有人需要工作示例:
<强> JS /动作/ actionTypes.js 强>
export const TRIGGER_SWITCH = 'TRIGGER_SWITCH';
<强> JS /动作/ switchActions.js 强>
import { TRIGGER_SWITCH } from './actionTypes';
export const triggerSwitch = value => ({
type: TRIGGER_SWITCH,
currentValue: value
});
<强> JS /减速器/ 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 /组件/ 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 /容器/ 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": {
"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"
},
答案 2 :(得分:0)
您是否正确绑定了_handleSwitch
功能? this.props.actions.triggerSwitch(value)
发送好吗?
使用redux-logger检查每个阶段的状态和操作,并确保您的组件在切换后收到正确的值。
答案 3 :(得分:0)
如果您正在编写与class Blah extends React
等ES6组件样式的反应,则需要使用.bind(this)
来更改运行时范围。
constructor(props) {
super(props)
this._handleSwitch = this._handleSwitch.bind(this);
}
这可能有效。或者关注@stereodenis的评论。这样做但每次重新渲染组件时,它都会创建方法。
答案 4 :(得分:0)
我面临着同样的问题。我的交换机组件位于FlatList中。尽管调用了render()方法,但开关值从未得到更新。结果,它恢复了原来的值。
为了解决这个问题,FlatList需要一种方法来知道它需要重新呈现列表。 Object.FindObjectOfType
用于此目的。
有关详细信息,请参见here。
答案 5 :(得分:0)
<Switch
onValueChange={this._handleSwitch}
value={(switch.currentValue) ? true : false}
/>
对我有用。
答案 6 :(得分:0)
对我来说,这是一个特定于Android的问题;如果不进行此修改,则可以在iOS上正常运行。必须中断默认事件传播并手动进行处理。这是一个使用钩子的示例,该钩子的逻辑在其他地方处理。您也可以使用
在本地处理它 [value, setValue] = useState()
,然后将setValue
用作您的handler
。
const Row = ({ onOff, handler, label }) => {
const onSwitchChange = evt => {
handler(evt.nativeEvent.value);
// Interrupt the default event and handle it manually
// Only necessary on Android but it also works on iOS so no branching necessary
evt.stopPropagation();
};
return (
<View style={styles.row}>
<View style={styles.label}>
<Text style={styles.labelText}>{label}</Text>
</View>
<Switch
style={styles.switchSize}
value={onOff}
onChangeCapture={onSwitchChange}
/>
</View>
);
};
答案 7 :(得分:-1)
我遇到过类似的问题(与redux无关)。对我来说,当交换机放在ListView中并且Switch的onValueChange中没有更新ListView的dataSource时,交换机会立即切换回来。
演示:https://rnplay.org/apps/tb6-fw
修正:https://rnplay.org/apps/FfoVmg
链接不再起作用,所以这里是ListView中的Switch无法正常工作的代码:
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View,
ListView,
Switch
} from 'react-native';
export default class SwitchTest extends Component {
constructor(props) {
super(props);
const ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
this.state = {
switch1Value: false,
switch2Value: false,
dataSource: ds.cloneWithRows([{ data: 'some row data...'}]),
};
}
render() {
return (
<View style={styles.container}>
<Switch
value={this.state.switch1Value}
onValueChange={value => this.setState({ switch1Value: value })}
/>
<View style={styles.listWrapper}>
<ListView
dataSource={this.state.dataSource}
renderRow={(rowData) => (
<View style={styles.row}>
<Text>{rowData.data}</Text>
<Switch
value={this.state.switch2Value}
onValueChange={value => this.setState({ switch2Value: value })}
/>
</View>
)}
/>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
listWrapper: {
height: 100,
padding: 10
},
row: {
flexDirection: 'row',
alignItems: 'center'
}
});
AppRegistry.registerComponent('SwitchTest', () => SwitchTest);
修复方法是在dataSource中移动switch2Value状态,并在Switch的onValueChange中更新dataSource。
// ...
this.state = {
switch1Value: false,
dataSource: ds.cloneWithRows([{ data: 'some row data...', switch2Value: false }]),
};
// ...
renderRow={(rowData) => (
<View style={styles.row}>
<Text>{rowData.data}</Text>
<Switch
value={rowData.switch2Value}
onValueChange={value => this.setState({
dataSource: this.state.dataSource.cloneWithRows([{ ...rowData, switch2Value: value }])
})}
/>
</View>
)}
// ...