[英]Radio button not working properly in react native
我正在制作本機反應的自定義單選按鈕。
父組件
const radioData = [
{ text: 'value A' },
{ text: 'value B' },
{ text: 'value C' },
];
<RadioButton
dataText={radioData}
isSelected={(selected) => {
console.log('<><>', selected);
}}
/>
子組件
const RadioButton= (props) => {
const [selected, setSelected] = useState(false);
let { dataText, isSelected } = props;
return (
<>
{dataText.map((item) => {
return (
<View
style={{
flexDirection: 'row',
width: '50%',
marginVertical: 10,
}}
>
{selected ? (
<TouchableOpacity
onPress={() => {
if (selected) {
setSelected(false);
isSelected(false);
} else {
setSelected(true);
isSelected(true);
}
}}
>
<Image
source={require('../../assets/img/checkFullColor.png')}
style={{
width: 20,
height: 20,
marginRight: 20,
}}
resizeMode={'contain'}
/>
</TouchableOpacity>
) : (
<TouchableOpacity
onPress={() => {
if (selected) {
setSelected(false);
isSelected(false);
} else {
setSelected(true);
isSelected(true);
}
}}
>
<View
style={{
backgroundColor: Colors.accentDark,
height: 20,
width: 20,
borderRadius: 50,
marginRight: 20,
}}
/>
</TouchableOpacity>
)}
<Text style={{ color: Colors.accentDark }}>{item.text}</Text>
</View>
);
})}
</>
);
};
問題是即使我單擊任何一個 RadioButton,然后所有 3 個都被選中或取消選中。
我想要一個功能,我單擊其中一個然后其他被取消選擇,並且選定的值在父組件中更新。
您的RadioButton
組件應該只渲染一個單選按鈕,而不是一次渲染所有單選按鈕。 所以你應該在父組件中映射radioData
。 現在, RadioButton
組件中映射的每個單選按鈕的selected
狀態都是相同的。
父組件的相關部分:
const radioData = [
{ text: 'value A' },
{ text: 'value B' },
{ text: 'value C' },
];
return render (
<View>
{radioData.map((item) => { <- map here
<RadioButton dataText={item.text} />
})
</View>
);
並刪除RadioButton
組件中的映射。
/...
return (
<>
// {dataText.map((item) => { <- remove this
/...
如果你想要一個渲染多個單選按鈕的組件,請將映射保留在RadioButton
組件中,但還要為每個單選按鈕設置狀態。 我強烈建議您不要這樣做,並將RadioComponent
限制為單選按鈕的一個實例。
我認為您的問題是您嘗試使用一個布爾值來跟蹤當前選擇的 RadioButton 是否存在。 如果您想使用布爾值來跟蹤,那么每個 radioData 項都需要一個布爾值,並且每次進行選擇時,都需要更新所有其他布爾值。 一種更簡單的方法是只跟蹤選定的索引,並比較索引:(這是一個小吃演示)
import React,{
useState,
useEffect
} from 'react';
import {
View,
Image,
TouchableOpacity,
// FlatList,
Text,
StyleSheet
} from 'react-native';
export default function RadioButton({onSelection,options, defaultSelection}){
// instead of giving each list item an isSelected prop just keep
// track of the selected index
const [selectedIndex, setSelectedIndex] = useState(defaultSelection || 0)
// its much cleaner to use an effect to allow subscriptions to changes
useEffect(()=>{
onSelection(selectedIndex,options[selectedIndex])
},[selectedIndex])
return (
<View style={styles.container}>
{
options.map((item,index)=>{
return (
<TouchableOpacity style={styles.rowItem} onPress={()=>setSelectedIndex(index)}>
{index == selectedIndex &&
<Image
source={require('../../assets/snack-icon.png')}
style={{
width: 20,
height: 20,
marginRight: 20,
}}
resizeMode={'contain'}
/>
}
<Text>{item.text}</Text>
</TouchableOpacity>
)
})
}
</View>
)
}
const styles = StyleSheet.create({
container:{
width:'100%',
height:'20%',
flexDirection: 'row',
flexWrap:'wrap',
justifyContent:'space-between',
alignItems:'center'
},
row:{
},
rowItem:{
// width: '50%',
paddingVertical:10,
marginVertical: 10,
}
})
和父組件:
import * as React from 'react';
import { Text, View, StyleSheet } from 'react-native';
import Constants from 'expo-constants';
import RadioButton from './src/components/RadioButton'
export default function App() {
const radioData = [
{ text: 'value A' },
{ text: 'value B' },
{ text: 'value C' },
];
return (
<View style={styles.container}>
<RadioButton
options={radioData}
onSelection={(index,value) => {
console.log('<><>', value);
}}
/>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
paddingTop: Constants.statusBarHeight,
backgroundColor: '#ecf0f1',
padding: 8,
},
paragraph: {
margin: 24,
fontSize: 18,
fontWeight: 'bold',
textAlign: 'center',
},
});
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.