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

React Native Todo应用点击单个任务触发全选完成的问题求助

问题原因

你在App组件里用了一个全局的isCompleted状态变量,所有Task组件都共享这个状态。点击任意任务时触发的是全局状态更新,所有任务都会读取同一个isCompleted值,因此全部同步切换完成状态。

解决方案

让每个任务独立维护自己的完成状态,而非依赖全局状态。具体修改如下:

1. 修改App.js

  • 移除全局的isCompleted状态
  • 调整任务数据结构,每个任务是包含text和isCompleted的对象
  • 添加切换单个任务完成状态的函数
  • 渲染Task时传递对应任务的状态和切换函数

修改后的App.js代码:

import { StatusBar } from 'expo-status-bar';
import { useState, React } from 'react';
import { StyleSheet, SafeAreaView, Text, View, TextInput, TouchableOpacity, Platform, Keyboard } from 'react-native';
import { useColorScheme } from "nativewind";
import Task from './components/Task.js'
import KeyboardAvoidingView from 'react-native/Libraries/Components/Keyboard/KeyboardAvoidingView.js';

export default function App() {
  const { colorScheme, toggleColorScheme } = useColorScheme();
  const [task, setTask] = useState()
  const [taskItems, setTaskItems] = useState([])

  const addTask = () => {
    Keyboard.dismiss()
    // 每个任务对象包含文本和完成状态
    setTaskItems([...taskItems, { text: task, isCompleted: false }])
    setTask(null)
  }

  // 切换指定索引任务的完成状态
  const toggleTaskCompletion = (index) => {
    const updatedTasks = [...taskItems];
    updatedTasks[index].isCompleted = !updatedTasks[index].isCompleted;
    setTaskItems(updatedTasks);
  }
 
  const deleteTask = () => {

  }
  const updateTask = () => {

  }
  return (
    <SafeAreaView className="bg-gray-500/20 flex-1 dark:bg-black/90 overflow-auto">
      <View className="w-full sticky top-0 left-0 flex items-end px-5 h-10 justify-center">
        <TouchableOpacity onPress={toggleColorScheme}>
          <Text className="dark:text-white">
            {colorScheme === "dark" ? `🌙 ${colorScheme}` : `🌞 ${colorScheme}`}
          </Text>
        </TouchableOpacity>
      </View>
      <View className="mt-5 px-5">
        {
          taskItems.map((item, index) => {
            // 传递单个任务的状态、切换函数和索引
            return <Task 
              key={index} 
              item={item} 
              toggleTaskCompletion={() => toggleTaskCompletion(index)} 
            />
          })
        }
      </View>

      <KeyboardAvoidingView style={styles.addTask}
        behavior={Platform.OS === "ios" ? "padding" : "height"}>
        <View>
          <TextInput onChangeText={text => setTask(text)}
            value={task}
            className="relative border px-5 py-5 border-gray-500/20 focus:border-gray-500 rounded-xl dark:text-white pr-16"
            placeholder='Lets! Tell me something to do' placeholderTextColor={colorScheme === "dark" ? "#fff" : "#000"}></TextInput>
          <TouchableOpacity
            onPress={() => addTask()}
            className="px-5 py-2 absolute right-0 top-0 h-full justify-center items-center">
            <Text>Add</Text>
          </TouchableOpacity>
        </View>
      </KeyboardAvoidingView>
      <StatusBar style="auto" />
    </SafeAreaView >
  );
}

const styles = StyleSheet.create({
  addTask: {
    position: 'absolute',
    left: 0,
    bottom: 40,
    width: "100%",
    paddingHorizontal: 20
  }
})

2. 修改Task组件

调整组件接收的props,使用单个任务的状态控制样式和文本效果,点击时触发对应任务的切换函数:

import React from "react";
import { View, Text, TouchableOpacity } from "react-native";

const Task = (props) => {
    return (
        <TouchableOpacity
            onPress={props.toggleTaskCompletion}
            className={`mt-5 dark:bg-white p-5 rounded-xl ${props.item.isCompleted ? 'bg-pink-200' : 'bg-white'}`}>
            <Text className={`${props.item.isCompleted ? 'text-white line-through' : ''}`}>
                {props.item.text}
            </Text>
        </TouchableOpacity>
    )
}

export default Task;

修改后每个任务都有独立的完成状态,点击单个任务只会切换该任务的状态,不会影响其他任务。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 19:35:33