You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Native:如何仅切换FlatList中指定项的状态?

FlatList 条件渲染 SwitchSelector 问题解决方案

问题描述

想要在FlatList中id为2、3、4的列表项旁添加SwitchSelector组件,但当前所有列表项都显示了该组件,使用了import SwitchSelector from "react-native-switch-selector";,希望解决这个条件渲染的问题。

Settings.js 原代码:

import { SafeAreaView,Text, View, FlatList,
TouchableOpacity, StyleSheet, Image} from 'react-native';
import SwitchSelector from "react-native-switch-selector";
import React, {useState} from 'react'



const Settings = () => {
    const [data, setdata] = useState(DATA);
    const [isRender, setisRender] = useState(false);

    const DATA = [
        {id: 1, text: 'Perfil', image: require('../../assets/images/user.png')},
        {id: 2, text: 'Dark/Light mode', image: require('../../assets/images/light-up.png')},
        {id: 3, text: 'TouchId', image: require('../../assets/images/fingerprint.png')},
        {id: 4, text: 'Notificações', image: require('../../assets/images/bell-fill.png')},
        //{id: 5, text: 'Logout'},
    ]

    const renderItem = ({item}) => {
        return(
        <TouchableOpacity style= {styles.item}>
            <View style={ styles.avatarContainer }>
               <Image source={ item.image } style={ styles.avatar } />
            </View>
            <View>
               <Text style={styles.text}>{item.text}</Text>
            </View>
        </TouchableOpacity>
        )
    }
    return (
    <SafeAreaView style={styles.container}>
    <FlatList
        data={DATA}
        keyExtractor={(item) => item.id.toString()}
        renderItem={renderItem}
        extraData={isRender}
    />
    </SafeAreaView>
    );
};

const styles = StyleSheet.create({
    container: {
        flex: 1,
        marginTop: 20
        //marginHorizontal: 21
    },
    item:{
        borderBottomWidth: 1,
        borderBottomColor: '#808080',
        alignItems: 'flex-start',
        flexDirection: 'row',
    },
    avatarContainer: {        
        backgroundColor: 'transparent',
        //borderRadius: 100,
        height: 30,
        width: 30,
        justifyContent: 'center',
        alignItems: 'center'
      },
      
      avatar: {
        height: 25,
        width: 25,
        bottom: -25,
        marginLeft: 30
      },
    text:{
        marginVertical: 30,
        fontSize: 20,
        fontWeight: 'bold',
        marginLeft: 30,
        marginBottom: 10,
        bottom: 5
    }
});

export default Settings;

解决方案

核心思路是在renderItem函数中根据item的id进行条件判断,只在id为2、3、4的项中渲染SwitchSelector组件,同时调整样式让开关显示在列表项右侧。

1. 修改renderItem函数

在返回的JSX中,通过includes方法判断当前item的id是否在目标数组[2,3,4]中,满足条件时才渲染SwitchSelector:

const renderItem = ({item}) => {
    // 定义SwitchSelector的选项(可根据需求调整)
    const switchOptions = [
        { label: "On", value: "on" },
        { label: "Off", value: "off" }
    ];

    return(
    <TouchableOpacity style= {styles.item}>
        <View style={styles.avatarContainer}>
           <Image source={ item.image } style={ styles.avatar } />
        </View>
        <View style={styles.textContainer}>
           <Text style={styles.text}>{item.text}</Text>
        </View>
        {/* 条件渲染SwitchSelector */}
        {[2,3,4].includes(item.id) && (
            <SwitchSelector
                options={switchOptions}
                initial={0}
                onPress={(value) => console.log(`Selected: ${value}`)}
                style={styles.switchStyle}
            />
        )}
    </TouchableOpacity>
    )
}

2. 调整样式

为了让SwitchSelector能正确显示在列表项右侧,需要修改item和新增相关样式:

const styles = StyleSheet.create({
    container: {
        flex: 1,
        marginTop: 20
    },
    item:{
        borderBottomWidth: 1,
        borderBottomColor: '#808080',
        alignItems: 'center', // 垂直居中对齐
        flexDirection: 'row',
        justifyContent: 'space-between', // 元素两端分布
        paddingRight: 20 // 给右侧开关留间距
    },
    avatarContainer: {        
        backgroundColor: 'transparent',
        height: 30,
        width: 30,
        justifyContent: 'center',
        alignItems: 'center'
    },
    avatar: {
        height: 25,
        width: 25,
        bottom: -25,
        marginLeft: 30
    },
    textContainer: {
        flex: 1, // 让文本容器占据中间剩余空间
    },
    text:{
        marginVertical: 30,
        fontSize: 20,
        fontWeight: 'bold',
        marginLeft: 30,
        marginBottom: 10,
        bottom: 5
    },
    switchStyle: {
        // 可根据需求调整开关的大小、间距等
        width: 120,
        height: 40
    }
});

完整修改后的代码

import { SafeAreaView,Text, View, FlatList,
TouchableOpacity, StyleSheet, Image} from 'react-native';
import SwitchSelector from "react-native-switch-selector";
import React, {useState} from 'react'

const Settings = () => {
    const [data, setdata] = useState(DATA);
    const [isRender, setisRender] = useState(false);

    const DATA = [
        {id: 1, text: 'Perfil', image: require('../../assets/images/user.png')},
        {id: 2, text: 'Dark/Light mode', image: require('../../assets/images/light-up.png')},
        {id: 3, text: 'TouchId', image: require('../../assets/images/fingerprint.png')},
        {id: 4, text: 'Notificações', image: require('../../assets/images/bell-fill.png')},
        //{id: 5, text: 'Logout'},
    ]

    const renderItem = ({item}) => {
        const switchOptions = [
            { label: "On", value: "on" },
            { label: "Off", value: "off" }
        ];

        return(
        <TouchableOpacity style= {styles.item}>
            <View style={styles.avatarContainer}>
               <Image source={ item.image } style={ styles.avatar } />
            </View>
            <View style={styles.textContainer}>
               <Text style={styles.text}>{item.text}</Text>
            </View>
            {[2,3,4].includes(item.id) && (
                <SwitchSelector
                    options={switchOptions}
                    initial={0}
                    onPress={(value) => console.log(`Selected: ${value}`)}
                    style={styles.switchStyle}
                />
            )}
        </TouchableOpacity>
        )
    }

    return (
    <SafeAreaView style={styles.container}>
    <FlatList
        data={DATA}
        keyExtractor={(item) => item.id.toString()}
        renderItem={renderItem}
        extraData={isRender}
    />
    </SafeAreaView>
    );
};

const styles = StyleSheet.create({
    container: {
        flex: 1,
        marginTop: 20
    },
    item:{
        borderBottomWidth: 1,
        borderBottomColor: '#808080',
        alignItems: 'center',
        flexDirection: 'row',
        justifyContent: 'space-between',
        paddingRight: 20
    },
    avatarContainer: {        
        backgroundColor: 'transparent',
        height: 30,
        width: 30,
        justifyContent: 'center',
        alignItems: 'center'
    },
    avatar: {
        height: 25,
        width: 25,
        bottom: -25,
        marginLeft: 30
    },
    textContainer: {
        flex: 1,
    },
    text:{
        marginVertical: 30,
        fontSize: 20,
        fontWeight: 'bold',
        marginLeft: 30,
        marginBottom: 10,
        bottom: 5
    },
    switchStyle: {
        width: 120,
        height: 40
    }
});

export default Settings;

关键说明

  • 条件渲染使用{condition && Component}的语法,只有当condition为true时才会渲染后面的组件。
  • 通过[2,3,4].includes(item.id)精准匹配需要显示开关的列表项id。
  • 调整item样式的justifyContent: 'space-between'让图标、文本和开关横向分布更合理,textContainer的flex:1确保文本区域占据中间空间。

内容的提问来源于stack exchange,提问作者Ann37

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 05:21:13