React Native + Redux:为什么 Switch 在切换到 true 后立即变回 false
React Native + Redux: Why does Switch immediately turns back to false after being switched to true?
在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
谢谢!
不是因为 redux,为了让Switch
工作,我们需要从状态显式设置value
,否则立即设置回false
<Switch
value={this.state.hasRead}
onValueChange={(value) => {
this.setState({
hasRead: value
})
}} />
我试图用 redux 和 Switch 重现所描述的问题,但我遇到的唯一问题是 switch 是一个保留字,所以我把它改成了 switchState。如果有人需要工作示例:
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/商店.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);
索引.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"
},
是否正确绑定了_handleSwitch
函数?this.props.actions.triggerSwitch(value)
调度可以吗?
使用 redux-logger 检查每个阶段的状态和操作,并确保组件在切换后收到正确的值。
如果你正在编写 react 与 ES6 组件样式,如 class Blah extends React
你需要使用 .bind(this)
来更改运行时范围。
constructor(props) {
super(props)
this._handleSwitch = this._handleSwitch.bind(this);
}
这也许有效。 或遵循@stereodenis 的评论。这样做是一样的,但每次重新渲染组件时,它都会创建方法。
我遇到了同样的问题。我的交换机组件在平面列表中。虽然调用了 render(( 方法,但开关值从未更新过。结果,它恢复到旧值。
为了解决这个问题,FlatList 需要一种方法来知道它需要重新呈现列表。 extraData
用于此目的。
有关详细信息,请参阅此处。
<Switch
onValueChange={this._handleSwitch}
value={(switch.currentValue) ? true : false}
/>
这对我有用。
对我来说,这是一个特定于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>
);
};
我遇到了类似的问题(与 redux 无关(。对我来说,当开关放置在列表视图中并且列表视图的数据源未在开关的onValueChange中更新时,开关会立即变回。
演示:https://rnplay.org/apps/tb6-fw
固定:https://rnplay.org/apps/FfoVmg
链接不再工作,因此以下是列表视图中的切换无法正常工作的代码:
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);
解决方法是在数据源中移动 switch2Value 状态,并在 Switch 的 onValueChange 中更新数据源。
// ...
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>
)}
// ...
- JavaScript-切换“;全部检查”;复选框true/false
- true==false以某种方式计算为true
- Javascript似乎在说true ==false
- JavaScript onkeydown, return true,false
- 从异步函数返回true/false以用于同步if()
- 函数返回undefined而不是true/false
- 为什么true/true是1,true/false是无穷大,false/true是0,false/false是NaN
- 检查对象数组是否包含布尔值true/false
- 函数:根据字符串中是否存在子字符串返回 True/False
- 如何将 ng-show 与控制器中返回 true/false 的函数一起使用
- 在input.checked=true/false _without_ jQuery上触发一个事件
- jQuery javascript未正确返回true/false
- 如何从嵌套的jquery回调函数中返回true/false
- 如何在骨干模型属性中设置布尔值true/false
- 如何使用angular或javascript在基于true/false返回的html中显示值
- 基于true/false变量显示/隐藏进度条
- Node.js在返回true/false时停止函数
- 是否可以将true/false值传递给ajax函数
- 根据Webix中的复选框值编辑true/false
- Meteor:设置车把变量true/false