Нарушение инварианта: попытка удалить отсутствующий дочерний список при попытке отрисовать вложенный Flatlist внутри основного FlatList

1
7

Это приложение для отслеживания тренировок. У меня есть два плоских списка. Один для отображения выбранного упражнения, а другой для отображения выполненных сетов. Когда не добавлено ни одного упражнения и я пытаюсь сменить вкладку, проблем не возникает. Но если я добавляю упражнение с одним сетом (по умолчанию), я сталкиваюсь с этой ошибкой

Это основной файл

club_room.jsx

TrackExercises.jsx

 Invariant Violation: Trying to remove non-present child list

This error is located at:
    in VirtualizedList (created by FlatList)
    in FlatList (created by CellRenderer)
    in RCTView (created by View)
    in View
    in NativeWind.View
    in Unknown (created by CellRenderer)
    in RCTView (created by View)
    in View (created by CellRenderer)
    in VirtualizedListCellContextProvider (created by CellRenderer)
    in CellRenderer (created by VirtualizedList)
    in RCTView (created by View)
    in View (created by ScrollView)
    in RCTScrollView (created by ScrollView)
    in ScrollView (created by ScrollView)
    in ScrollView (created by VirtualizedList)
    in VirtualizedListContextProvider (created by VirtualizedList)
    in VirtualizedList (created by FlatList)
    in FlatList (created by TrackExercises)
    in RCTView (created by View)
    in View
    in NativeWind.View
    in Unknown (created by TrackExercises)
    in TrackExercises (created by Club_Room)
    in RCTView (created by View)
    in View
    in NativeWind.View
    in Unknown (created by Club_Room)
    in RCTView (created by View)
    in View (created by ScrollView)
    in RCTScrollView (created by ScrollView)
    in ScrollView (created by ScrollView)
    in ScrollView
    in NativeWind.ScrollView
    in Unknown (created by Club_Room)
    in RCTView (created by View)
    in View
    in NativeWind.View
    in Unknown (created by Club_Room)
    in Club_Room
    in Unknown (created by Route(club_room))
    in Suspense (created by Route(club_room))
    in Route (created by Route(club_room))
    in Route(club_room) (created by SceneView)
    in StaticContainer
    in EnsureSingleNavigator (created by SceneView)
    in SceneView (created by SceneView)
    in RCTView (created by View)
    in View (created by DebugContainer)
    in DebugContainer (created by MaybeNestedStack)
    in MaybeNestedStack (created by SceneView)
    in RCTView (created by View)
    in View (created by SceneView)
    in RNSScreen (created by Animated(Anonymous))
    in Animated(Anonymous) (created by InnerScreen)
    in Suspender (created by Freeze)
    in Suspense (created by Freeze)
    in Freeze (created by DelayedFreeze)
    in DelayedFreeze (created by InnerScreen)
    in InnerScreen (created by Screen)
    in Screen (created by SceneView)
    in SceneView (created by NativeStackViewInner)
    in Suspender (created by Freeze)
    in Suspense (created by Freeze)
    in Freeze (created by DelayedFreeze)
    in DelayedFreeze (created by ScreenStack)
    in RNSScreenStack (created by ScreenStack)
    in ScreenStack (created by NativeStackViewInner)
    in NativeStackViewInner (created by NativeStackView)
    in RCTView (created by View)
    in View (created by SafeAreaProviderCompat)
    in SafeAreaProviderCompat (created by NativeStackView)
    in NativeStackView (created by NativeStackNavigator)
    in PreventRemoveProvider (created by NavigationContent)
    in NavigationContent
    in Unknown (created by NativeStackNavigator)
    in NativeStackNavigator
    in Unknown (created by RoomLayout)
    in RoomLayout
    in Unknown (created by Route((room)))
    in Suspense (created by Route((room)))
    in Route (created by Route((room)))
    in Route((room)) (created by SceneView)
    in StaticContainer
    in EnsureSingleNavigator (created by SceneView)
    in SceneView (created by SceneView)
    in RCTView (created by View)
    in View (created by DebugContainer)
    in DebugContainer (created by MaybeNestedStack)
    in MaybeNestedStack (created by SceneView)
    in RCTView (created by View)
    in View (created by SceneView)
    in RNSScreen (created by Animated(Anonymous))
    in Animated(Anonymous) (created by InnerScreen)
    in Suspender (created by Freeze)
    in Suspense (created by Freeze)
    in Freeze (created by DelayedFreeze)
    in DelayedFreeze (created by InnerScreen)
    in InnerScreen (created by Screen)
    in Screen (created by SceneView)
    in SceneView (created by NativeStackViewInner)
    in Suspender (created by Freeze)
    in Suspense (created by Freeze)
    in Freeze (created by DelayedFreeze)
    in DelayedFreeze (created by ScreenStack)
    in RNSScreenStack (created by ScreenStack)
    in ScreenStack (created by NativeStackViewInner)
    in NativeStackViewInner (created by NativeStackView)
    in RCTView (created by View)
    in View (created by SafeAreaProviderCompat)
    in SafeAreaProviderCompat (created by NativeStackView)
    in NativeStackView (created by NativeStackNavigator)
    in PreventRemoveProvider (created by NavigationContent)
    in NavigationContent
    in Unknown (created by NativeStackNavigator)
    in NativeStackNavigator
    in Unknown (created by RootLayout)
    in GlobalProvider (created by RootLayout)
    in RootLayout
    in Unknown (created by Route())
    in Suspense (created by Route())
    in Route (created by Route())
    in Route() (created by ContextNavigator)
    in RNCSafeAreaProvider (created by SafeAreaProvider)
    in SafeAreaProvider (created by wrapper)
    in wrapper (created by ContextNavigator)
    in EnsureSingleNavigator
    in BaseNavigationContainer
    in ThemeProvider
    in NavigationContainerInner (created by ContextNavigator)
    in ContextNavigator (created by ExpoRoot)
    in ExpoRoot (created by App)
    in App (created by ErrorOverlay)
    in ErrorToastContainer (created by ErrorOverlay)
    in ErrorOverlay (created by withDevTools(ErrorOverlay))
    in withDevTools(ErrorOverlay)
    in RCTView (created by View)
    in View (created by AppContainer)
    in RCTView (created by View)
    in View (created by AppContainer)
    in AppContainer
    in main(RootComponent), js engine: hermes
 ERROR  AggregateError: , js engine: hermes
import {
  View,
  Text,
  SafeAreaView,
  ScrollView,
  Image,
  TouchableOpacity,
} from "react-native";
import React, { useEffect, useState } from "react";
import { router, useLocalSearchParams } from "expo-router";
import SmallButton from "../../components/SmallButton";
import icons from "../../constants/icons";
import TrackExercises from "../../components/TrackExercises";

import { useGlobalContext } from "../../context/GlobalProvider";

const Club_Room = () => {
  const { name, selectedExercise } = useLocalSearchParams();
  const [currentTab, setCurrentTab] = useState("Track");
  const { exercises, setExercises } = useGlobalContext();
  
  console.log(JSON.stringify(exercises));

  const addExercise = (exerciseName) => {
    const newExercise = {
      name: exerciseName,
      sets: [{ weight: "", reps: "", done: false }],
    };

    JSON.stringify(newExercise.sets);
    setExercises([...exercises, newExercise]);
  };

  useEffect(() => {
    if (selectedExercise) {
      addExercise(selectedExercise);
    }
  }, [selectedExercise]);

  return (
    <SafeAreaView className="w-full h-full bg-black flex items-center justify-center px-4 pt-7">
      <ScrollView className="w-full h-full">
        <View className="w-full h-full flex justify-between items-start">
          <TouchableOpacity onPress={() => router.push("/home")}>
            <Image
              source={icons.left_arrow}
              resizeMode="contain"
              className="w-9 h-9"
            />
          </TouchableOpacity>
          <Text className="text-white font-msemibold text-lg mt-2">{name}</Text>
          <View className="w-full flex-row mt-2 justify-between items-center bg-grey rounded-lg">
            <SmallButton
              title="Explore"
              containerStyles={
                currentTab === "Explore" ? "bg-primary" : "bg-grey"
              }
              textStyles={
                currentTab === "Explore"
                  ? "font-msemibold text-black"
                  : "font-mregular text-white"
              }
              handlePress={() => setCurrentTab("Explore")}
            />
            <SmallButton
              title="Track"
              containerStyles={
                currentTab === "Track" ? "bg-primary" : "bg-grey"
              }
              textStyles={
                currentTab === "Track"
                  ? "font-msemibold text-black"
                  : "font-mregular text-white"
              }
              handlePress={() => setCurrentTab("Track")}
            />
            <SmallButton
              title="Pinned"
              containerStyles={
                currentTab === "Pinned" ? "bg-primary" : "bg-grey"
              }
              textStyles={
                currentTab === "Pinned"
                  ? "font-msemibold text-black"
                  : "font-mregular text-white"
              }
              handlePress={() => setCurrentTab("Pinned")}
            />
          </View>
          {currentTab === "Track" && <TrackExercises />}
        </View>
      </ScrollView>
    </SafeAreaView>
  );
};

export default Club_Room;

import {
  View,
  Text,
  FlatList,
  TouchableOpacity,
  Image,
  TextInput,
  SafeAreaView,
} from "react-native";
import React, { useEffect } from "react";
import icons from "../constants/icons";
import { router } from "expo-router";
import { useGlobalContext } from "../context/GlobalProvider";

eg_list = [
  {
    num: 1,
  },
  {
    num: 2,
  },
];

const TrackExercises = () => {
  const { exercises, setExercises } = useGlobalContext();

  // console.log(JSON.stringify(localExercises));

  const addSet = (exerciseIndex) => {
    const newExercises = [...exercises];
    if (newExercises[exerciseIndex]) {
      newExercises[exerciseIndex].sets.push({ weight: "", reps: "" });
      setExercises(newExercises);
    }
  };

  const toggleDone = (exerciseIndex, setIndex) => {
    const newExercises = [...exercises];
    if (
      newExercises[exerciseIndex] &&
      newExercises[exerciseIndex].sets[setIndex]
    ) {
      const set = newExercises[exerciseIndex].sets[setIndex];
      set.done = !set.done;
      setExercises(newExercises);
      //update db
    }
  };

  const registerSet = (exerciseIndex, setIndex, weight, reps) => {
    const newExercises = [...exercises];
    if (newExercises[exerciseIndex].sets[setIndex]) {
      if (weight !== null) {
        newExercises[exerciseIndex].sets[setIndex].weight = weight;
      }
      if (reps !== null) {
        newExercises[exerciseIndex].sets[setIndex].reps = reps;
      }
      setExercises(newExercises);
    }
  };

  return (
    <SafeAreaView className="w-full flex justify-center items-center">
      <FlatList
        data={exercises}
        scrollEnabled={false}
        horizontal={false}
        showsVerticalScrollIndicator={false}
        keyExtractor={(item) => item.$id}
        renderItem={({ item, index }) => (
          <View
            key={item.$id}
            className="flex items-center justify-center mt-7"
          >
            <View className="w-full flex-row justify-between items-center">
              <Text className="text-primary text-left font-mregular text-lg">
                {item.name}
              </Text>
              <TouchableOpacity>
                <Image
                  source={icons.three_dots_green}
                  resizeMode="contain"
                  className="w-5 h-5"
                />
              </TouchableOpacity>
            </View>
            <View className="mt-2 w-full flex-row justify-between items-center space-x-4">
              <Text
                style={styles.setCol}
                className="text-white text-center text-sm font-mregular"
              >
                SET
              </Text>
              <Text
                style={styles.prevCol}
                className="text-white text-center text-sm font-mregular"
              >
                PREVIOUS
              </Text>
              <Text
                style={styles.kgCol}
                className="text-white text-center text-sm font-mregular"
              >
                KG
              </Text>
              <Text
                style={styles.repsCol}
                className="text-white text-center text-sm font-mregular"
              >
                REPS
              </Text>
              <Text
                style={styles.checkCol}
                className="text-white text-center text-sm font-mregular"
              ></Text>
            </View>
            <FlatList
              data={item.sets ? item.sets : []}
              horizontal={false}
              showsVerticalScrollIndicator={false}
              nestedScrollEnabled={true}
              keyExtractor={(setItem, setIndex) => `${setItem.$id}-${setIndex}`}
              renderItem={({ item, index: setIndex }) => (
                <View
                  key={item.$id}
                  className="mt-2 w-full flex-row justify-between items-center space-x-4"
                >
                  <Text
                    style={styles.setCol}
                    className="text-white text-center text-sm font-mregular"
                  >
                    {setIndex + 1}
                  </Text>
                  <Text
                    style={styles.prevCol}
                    className="text-white text-center text-sm font-mregular"
                  ></Text>
                  <TextInput
                    keyboardType="numeric"
                    style={styles.kgCol}
                    className="bg-grey rounded-md text-center text-white"
                    onChangeText={(e) => {
                      registerSet(index, setIndex, e, null);
                    }}
                    defaultValue={exercises[index].sets[setIndex].weight}
                  />
                  <TextInput
                    keyboardType="numeric"
                    style={styles.repsCol}
                    className="bg-grey rounded-md text-center text-white"
                    onChangeText={(e) => {
                      registerSet(index, setIndex, null, e);
                    }}
                    defaultValue={exercises[index].sets[setIndex].reps}
                  />
                  <TouchableOpacity
                    onPress={() => {
                      toggleDone(index, setIndex);
                    }}
                  >
                    <Image
                      style={styles.checkCol}
                      source={
                        item.done ? icons.set_checked : icons.set_unchecked
                      }
                      resizeMode="contain"
                      className="w-7 h-7"
                    />
                  </TouchableOpacity>
                </View>
              )}
            />
            <TouchableOpacity onPress={() => addSet(index)}>
              <Text className="mt-4 text-primary font-mregular text-lg">
                ADD SET
              </Text>
            </TouchableOpacity>
          </View>
        )}
      />

      <View className="my-4 w-full flex justify-center items-center space-y-7">
        <TouchableOpacity onPress={() => router.push("/select_exercise")}>
          <Text className="text-primary font-mregular text-lg ">
            ADD EXERCISE
          </Text>
        </TouchableOpacity>
      </View>
    </SafeAreaView>
  );
};

const styles = {
  setCol: {
    flex: 1,
  },
  prevCol: {
    flex: 2,
  },
  kgCol: {
    flex: 1,
  },
  repsCol: {
    flex: 1,
  },
  checkCol: {
    flex: 1,
  },
};

export default TrackExercises;

Николай
Вопрос задан3 июля 2024 г.

1 Ответ

2
Август
Ответ получен9 сентября 2024 г.

Ваш ответ

Загрузить файл.