I'm trying to make multiple switches, the problem is that when I enable / disable 1, all others enable / disable together.
useEffect is being used for me to bring my data from my API.
const [data, setData] = useState([]);
useEffect(() => {
async function fetchData() {
await api
.get('/synchronization/group/true')
.then(response => setData(response.data.data))
.catch(error => setData(error));
}
fetchData();
}, []);
useEffect(() => {
// Just return data
}, [data]);
const [isEnabled, setIsEnabled] = useState({
enabled: false
});
const toggleSwitch = () => setIsEnabled((toggle) => !toggle);
const Item = ({ id, title }) => {
return (
<View>
<TextList>{title}</TextList>
<Switch
key={id}
onValueChange={toggleSwitch}
value={isEnabled}
/>
</View>
);
};
And here my render switches with looping, It adds component according to the records in the database
const renderItem = ({ item }) => {
const date = new Date(item.synchronization)
const formattedDate = date.toISOString().split('T')[0];
return <Item id={item.id} title={'Sincronização: ' formattedDate.split('-').reverse().join('/')} />
};
return (
<Container>
<List
data={data}
renderItem={renderItem}
keyExtractor={item => item.id.toString()}
/>
<TouchableButton onPress={() => { navigation.navigate('Loading') }}>
<TextButton>Carregar para offline</TextButton>
</TouchableButton>
</Container>
);
}
My screen:
CodePudding user response:
If I understand correctly, all the code that you provided is in one component. You need to store the state of switch button separately.
Try it:
const Item = ({id, title, value, onValueChange}) => (
<View>
<TextList>{title}</TextList>
<Switch
onValueChange={onValueChange}
value={value}
/>
</View>
);
const Component = ({navigation}) => {
const [data, setData] = useState([]);
useEffect(() => {
const fetchData = async () => {
await api
.get('/synchronization/group/true')
.then(response => setData(response.data.data))
.catch(error => setData(error));
}
fetchData();
}, []);
useEffect(() => {
// Just return data
}, [data]);
const [state, setState] = useState({
switches: {}
});
const toggleSwitch = useCallback((id) => () => setState((state) => ({
...state,
switches: {
...state.switches,
[id]: !state.switches[id]
}
})), []);
const renderItem = useCallback(({item}) => {
const date = new Date(item.synchronization)
const formattedDate = date.toISOString().split('T')[0];
return <Item id={item.id} title={'Sincronização: ' formattedDate.split('-').reverse().join('/')} value={!!state.switches[item.id]} onValueChange={toggleSwitch(item.id)}/>
}, [state.switches, toggleSwitch]);
return (
<Container>
<List
data={data}
renderItem={renderItem}
keyExtractor={item => item.id.toString()}
/>
<TouchableButton onPress={() => navigation.navigate('Loading')}>
<TextButton>Carregar para offline</TextButton>
</TouchableButton>
</Container>
);
};
CodePudding user response:
If you don't need to store states of all switches in your parent component, you can declare state in a component that will be rendered in list.
Here you declare state, that will be handled locally in this component.
const SwitchComponent = (item => {
const [switchState, setSwitchState] = useState(item.state)
return (
<Switch value={switchState} onValueChange={ () => setSwitchState(prevState => !prevState)}/>
)
})
then it can be rendered in List
<View style={styles.container}>
{arr.map(item => (<SwitchComponent item={item}/>))}
</View>
Rendering as many switches as you want, with state handled separately.
You can try it here.