React Native Switch 同步未按预期工作

问题描述 投票:0回答:1

我的目标很简单。当我在当天有一个日程安排时,我希望开关打开。如果没有,我希望开关关闭。这是由 validateIsOut 函数控制的。

我可以选择添加新计划或删除它们,当我这样做时,切换总是落后一步。如果我添加当天的事件,开关不会移动。然后如果我删除这个事件,开关就会打开(总是落后一步)




export default function AwayOn() {

//Other code irrelevant for this issue

  //############################//
  //        USE-EFFECTS         //
  //############################//

  //useEffect to populate the collaborators dropdown.
  useEffect(() => {
    getUserData();
  }, []);

  useEffect(() => {
    validateIsOut();
  }, [schedules]);

  //############################//
  //         USE_STATE          //
  //############################//



  //State to control if user is away or not
  const [isOut, setIsOut] = useState(false);

  //State with test schedules
  const [schedules, setSchedules] = useState({
    "2024-08-01": [{ name: "Meeting 1", data: "teste" }],
    "2024-08-20": [{ name: "Meeting 1", data: "teste" }],
    "2024-08-21": [{ name: "Meeting 2", data: "teste" }],
  });

//Other code irrelevant for this issue

  //############################//
  //         FUNCTIONS          //
  //############################//

  //Function to add a new schedule
  const addNewSchedule = () => {
    const newSchedule = {
      name: newRegisterTitle,
      data: newRegisterDescription,
    };

    const dateKey = newRegisterDate.toISOString().split("T")[0];

    setSchedules((prevItems) => {
      return {
        ...prevItems,
        [dateKey]: [newSchedule],
      };
    });

    setOpenModal(false);
    setNewRegisterTitle("");
    setNewRegisterDescription("");
    setNewRegisterDate(new Date());
  };

  //Function to close the modal
  const closeModal = () => {
    setOpenModal(false);
    setNewRegisterDate(new Date());
    setNewRegisterDescription("");
    setNewRegisterTitle("");
    setDeleteRegister(false);
  };

  //Function to delete an existing schedule
  const deleteSchedule = () => {
    const dateKey = newRegisterDate.toISOString().split("T")[0];

    setSchedules((prevItems) => {
      const updatedItems = { ...prevItems };
      delete updatedItems[dateKey];

      return updatedItems;
    });

    closeModal();
  };

 

 //Other code irrelevant for this issue

  const validateIsOut = () => {
    let today = new Date().toISOString().split("T")[0];
    if (schedules[today]) {
      console.log("User is out");
      setIsOut(true);
    } else {
      console.log("User is present");
      setIsOut(false);
    }
  };

  //++++++++++++++++++++++++++RETURN++++++++++++++++++++++++++++++//
  //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//

  return (
    <>
      <View style={backgroundStyles.container}>
        <Header />
        <ImageBackground
          source={require("../../assets/image/LOGOTIPO_MECWIDE_M_ONLY.png")}
          style={backgroundStyles.backgroundImage}
          imageStyle={backgroundStyles.imageBackgroundStyle}
        ></ImageBackground>
        <View style={styles.header}>
          <View style={styles.headerContainerTitle}>
            <Text style={globalStyles.headerTitle}>{title[lang]}</Text>
          </View>
          <View style={styles.headerRight}></View>
        </View>
        <View
          style={[
            globalStyles.mb20,
            { flexDirection: "row", alignItems: "center" },
          ]}
        >
          <Switch
            trackColor={{ false: "#767577", true: "#0050F2" }}
            thumbColor={isOut ? "#f4f3f4" : "#f4f3f4"}
            ios_backgroundColor="#3e3e3e"
            value={isOut}
            disabled={true}
            style={globalStyles.mr10}
          />
          <Text style={[globalStyles.whiteColor]}>{toggle2[lang]}</Text>
        </View>
        <View
          style={[globalStyles.mb20, globalStyles.flex1, { maxHeight: 350 }]}
        >
          <Agenda
            items={allDates}
            renderItem={(item, isFirst) => (
              <TouchableOpacity style={styles.item}>
                <Text style={[styles.itemText, globalStyles.bold]}>
                  {item.name}
                </Text>
                <Text style={styles.itemText}>{item.data}</Text>
              </TouchableOpacity>
            )}
            pastScrollRange={0}
            futureScrollRange={2}
            style={{ borderRadius: 10 }}
          />
        </View>
        {!isOtherUserStatus && (
          <TouchableOpacity
            style={[btnsStyles.submitButton, btnsStyles.shadow]}
            onPress={() => setOpenModal(true)}
          >
            <Text style={btnsStyles.submitButtonText}>{btn1[lang]}</Text>
          </TouchableOpacity>
        )}
        <Modal
          animationType="slide"
          transparent={true}
          visible={openModal}
          onRequestClose={closeModal}
        >
          <View style={modalStyles.modalBackground}>
            <View style={modalStyles.modalContent}>
              <View style={styles.modalHeader}>
                <Text
                  style={[
                    globalStyles.greyColor3,
                    globalStyles.bold,
                    { fontSize: 16 },
                  ]}
                >
                  {modalTitle[lang]}
                </Text>
                <AntDesign
                  name="closecircle"
                  size={24}
                  color="#333333"
                  onPress={closeModal}
                />
              </View>
              <View style={[globalStyles.mb10, styles.rowCenter]}>
                <Text>{toggle3[lang]}</Text>
                <Switch
                  trackColor={{ false: "#0050F2", true: "red" }}
                  thumbColor={deleteRegister ? "#f4f3f4" : "#f4f3f4"}
                  ios_backgroundColor="#0050F2"
                  onValueChange={toggleSwitchSchedule}
                  value={deleteRegister}
                  style={[globalStyles.mr10, globalStyles.ml10]}
                />
                <Text>{toggle4[lang]}</Text>
              </View>
              <View
                style={[
                  globalStyles.mb20,
                  styles.rowCenter,
                  {
                    justifyContent: "flex-start",
                  },
                ]}
              >
                <Text style={globalStyles.mr10}>{date[lang]} </Text>
                {Platform.OS === "android" && (
                  <View style={[{ flexDirection: "row" }, styles.lineWrapper]}>
                    <TouchableOpacity
                      onPress={() => {
                        setShow(true);
                        setMode("date");
                      }}
                      style={{ width: 150 }}
                    >
                      <View
                        style={[
                          autoCompleteDropsStyles.textAreaContainer,
                          styles.androidCalendar,
                        ]}
                      >
                        <AntDesign name="calendar" size={25} color="#333" />

                        <Text style={globalStyles.greyColor3}>
                          {newRegisterDate.toLocaleDateString()}
                        </Text>
                      </View>
                    </TouchableOpacity>
                  </View>
                )}
                {Platform.OS === "android" && show && (
                  <DateTimePicker
                    testID="dateTimePicker"
                    value={newRegisterDate}
                    mode={mode}
                    is24Hour={true}
                    display="default"
                    onChange={handleDateChange}
                  />
                )}
                {Platform.OS === "ios" && (
                  <View>
                    <DateTimePicker
                      testID="dateTimePicker"
                      value={newRegisterDate}
                      mode="date"
                      is24Hour={true}
                      display="default"
                      onChange={handleDateChange}
                      themeVariant="light"
                      style={[
                        styles.rowCenter,
                        {
                          justifyContent: "center",
                          width: 100,
                        },
                      ]}
                    />
                  </View>
                )}
              </View>
              <TextInput
                style={[
                  autoCompleteDropsStyles.textAreaContainer,
                  styles.titleInput,
                  deleteRegister && { opacity: 0.5 },
                ]}
                placeholder={titleInput[lang]}
                multiline={false}
                placeholderTextColor={"#000"}
                value={newRegisterTitle}
                onChangeText={handleTitleChange}
                editable={!deleteRegister}
              />
              <TextInput
                style={[
                  autoCompleteDropsStyles.textAreaContainer,
                  styles.descriptionInput,
                  deleteRegister && { opacity: 0.5 },
                ]}
                placeholder={descriptionInput[lang]}
                multiline={true}
                placeholderTextColor={"#000"}
                value={newRegisterDescription}
                onChangeText={handleDescriptionChange}
                editable={!deleteRegister}
              />
              {!deleteRegister && (
                <TouchableOpacity
                  style={[
                    btnsStyles.submitButton,
                    btnsStyles.shadow,
                    {
                      opacity:
                        !newRegisterTitle || !newRegisterDescription ? 0.5 : 1,
                    },
                  ]}
                  onPress={() => {
                    addNewSchedule();
                    validateIsOut();
                  }}
                  disabled={!newRegisterTitle || !newRegisterDescription}
                >
                  <Text style={btnsStyles.submitButtonText}>{btn2[lang]}</Text>
                </TouchableOpacity>
              )}
              {deleteRegister && (
                <TouchableOpacity
                  style={[btnsStyles.deleteButton, btnsStyles.shadow]}
                  onPress={() => {
                    deleteSchedule();
                    validateIsOut();
                  }}
                >
                  <Text style={btnsStyles.submitButtonText}>{btn3[lang]}</Text>
                </TouchableOpacity>
              )}
            </View>
          </View>
        </Modal>
      </View>
      <Footer />
    </>
  );
}

//++++++++++++++++++++++++++++STYLES++++++++++++++++++++++++++++//
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//

const styles = StyleSheet.create({
  androidCalendar: {
    flexDirection: "row",
    justifyContent: "space-evenly",
    alignItems: "center",
    marginBottom: 0,
    backgroundColor: "#EEE",
    borderColor: "#EEE",
  },
  descriptionInput: {
    height: 60,
    backgroundColor: "#EEE",
    borderColor: "#EEE",
    textAlignVertical: "top",
  },
  header: {
    flexDirection: "row",
    justifyContent: "space-between",
    alignItems: "center",
    marginBottom: 30,
  },
  headerContainerTitle: {
    display: "flex",
    flexDirection: "row",
    alignItems: "center",
  },
  headerRight: {
    flexDirection: "row",
    alignItems: "center",
  },
  item: {
    backgroundColor: "lightblue",
    flex: 1,
    borderRadius: 5,
    padding: 10,
    marginRight: 10,
    marginTop: 25,
    paddingBottom: 20,
  },
  itemText: {
    color: "#000",
    fontSize: 14,
  },
  lineWrapper: {
    flexDirection: "row",
    width: "100%",
    justifyContent: "space-between",
  },
  modalHeader: {
    flexDirection: "row",
    justifyContent: "space-between",
    alignContent: "center",
    marginBottom: 20,
  },
  rowCenter: {
    flexDirection: "row",
    alignItems: "center",
  },
  titleInput: {
    height: 30,
    backgroundColor: "#EEE",
    borderColor: "#EEE",
  },
});

我已经尝试过使用 useEffect 但不起作用。我还尝试在调用 validateIsOut 函数时使用 setTimeOut 但也不起作用。

react-native
1个回答
0
投票

而不是

useEffect(() => {
    validateIsOut();
  }, [schedules]);

// Some code

const [isOut, setIsOut] = useState(false);

这样写

const [isOut, setIsOut] = useState(false);
 
// Some code

useEffect(() => {
    validateIsOut();
  }, [schedules]);

把这个useEffect放在这个useState后面然后尝试。

© www.soinside.com 2019 - 2024. All rights reserved.