【问题标题】:ToDo complete status not staying saved in storage in React NativeToDo 完成状态不会保存在 React Native 的存储中
【发布时间】:2022-12-10 22:24:25
【问题描述】:

编辑 - 添加了最低限度的可复制示例:https://snack.expo.dev/@hdorra/code

我希望每个人都可以访问小吃。所以如果你添加一个任务,你可以看到它显示在日志中。单击圆圈,它显示为 true(表示已单击)。保存并刷新,一切都被存储(任务)但复选框没有。我剥离了代码以使其尽可能少,但它显示了问题。

我已经好几天没犯这个错误了。我是 stackoverflow 的新手,所以如果我的问题不清楚或者我没有以正确的格式提问,我深表歉意。我正在尝试在使用异步存储的 React Native 中创建一个待办事项应用程序。我创建了一个切换按钮,将切换保存到一个状态。这个按钮位于一个组件中:

 const [checkBoxState, setCheckBoxState] = React.useState(false);

 const toggleComplete = () => {

        setCheckBoxState(!checkBoxState)
        handleEdit();
        console.log(checkBoxState)

    }

当用户检查它时 - 似乎在控制台中正确显示为标记为真和假。 然后,这被传递给编辑处理程序以更新数组,控制台再次显示它是正确的状态:

  const handleEdit = () => {
        props.editHandler(props.todoKey, text, checkBoxState);
        console.log(text2, checkBoxState)
    };

然后显示保存正确:

 const [todos, setTodos] = React.useState([]);
 const handleEdit = (todoKey, text, newStatus) => {
        const newTodos = [...todos];
        const index = newTodos.findIndex(todos => todos.key === todoKey);
        newTodos[index] = Object.assign(newTodos[index], {title: text, status: newStatus});
        setTodos(newTodos);
    
        console.log(todos, newStatus)
    };

保存到设备和加载的异步函数如下: 保存:

const saveTodoToUserDevice = async (todos) => {
        try {
            const stringifyTodos = JSON.stringify(todos);
            await AsyncStorage.setItem('todos', stringifyTodos);
        } catch (error) {
            console.log(error);
        }
    };

从设备加载:

const getTodosFromUserDevice = async () => {
        try {
            const todos = await AsyncStorage.getItem('todos');
            if (todos != null) {
                setTodos(JSON.parse(todos));
                console.log("loaded successfully");
            }
        } catch (error) {
            console.log(error);
        }
    };

所以这就是问题所在 - 我得到的控制台日志表明它已正确保存并加载。但是,当我刷新时,复选框状态根本没有保存,只保存了标题文本(所以它正在保存但复选框将始终为假(初始状态集)。如果我点击 true,它将显示为 true 和然后当我刷新时,它又回到错误。

我在这上面花了很多天,但无法弄清楚。任何方向都会有帮助谢谢!

【问题讨论】:

  • 欢迎用户15928679!在将问题粘贴到 Stack Overflow 时,我们是否假设这个 [checkboxChecked, setCheckboxChecked=useState(false) 是拼写错误?
  • 哦,很抱歉!是的,它是:const [checkBoxState, setCheckBoxState] = React.useState(false);
  • 任何帮助将不胜感激,我已经花了 DAYS 并查看了 stackoverflow 上的每个可能的答案。它不是重新渲染,它是识别状态(选中与不在数组中),其他一切都在保存,但任何刷新,它们都会回到基线 false。我认为这可能与它不是字符串有关,而是 savetodos 和 gettodos 函数相应地进行字符串化和解析。
  • handleEdit中的setTodos(newTodos);之后,你不会打电话给saveTodoToUserDevice(newTodos)吧?
  • 如果您可以添加所有相关代码以使其成为minimal, reproducible example,那就太好了。就像在您粘贴了那些特定代码的地方添加组件一样。您可以编辑您的帖子。

标签: javascript reactjs react-native asyncstorage


【解决方案1】:

我查看了你的code,发现你在不同的地方犯了一些错误。在 Task.js 中,您可以不用 checkBoxState。为此,将status作为props传递给Task,同时在FlatList中渲染它,如下所示:

<Task
  key={item.key}
  todoKey={item.key}
  title={item.title}
  status={item.status}
  editHandler={handleEdit}
  pressHandler={handleDelete}
/>

然后如下所示,更改按钮以切换 status,因此您使用来自 props 的内容并创建一个名为 toggleStatus 的函数并将其传递给 onPress

<TouchableOpacity onPress={toggleStatus}>
  <View
    style={[
      styles.circle,
      !props.status ? styles.completeCircle : styles.incompleteCircle,
    ]}
  ></View>
</TouchableOpacity>

toggleStatus的代码:

const toggleStatus = () => {
  props.editHandler(props.todoKey, props.title, !props.status);
};

handleEdit 将被简化为:

const handleEdit = () => {
  props.editHandler(props.todoKey, text2, props.status);
  setEdit(false);
  console.log(props.status);
};

最后,在 TasksMain.js 中,所以你不要用提供给 useState 的初始数组替换存储中的内容,确保 saveTodoToUserDevicegetTodosFromUserDevice 之后运行。为此,在 TasksMain.js 中添加以下状态并稍微更改两个函数,如下所示:

const [loading, setLoading] = React.useState(true);
const saveTodoToUserDevice = async (todos) => {
  if (loading) return;
  try {
    const stringifyTodos = JSON.stringify(todos);
    await AsyncStorage.setItem("todos", stringifyTodos);
  } catch (error) {
    console.log(error);
  }
};
const getTodosFromUserDevice = async () => {
  try {
    const todos = await AsyncStorage.getItem("todos");
    if (todos != null) {
      setTodos(JSON.parse(todos));
      console.log("loaded successfully");
    }
  } catch (error) {
    console.log(error);
  } finally {
    setLoading(false);
  }
};

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-08-17
    • 1970-01-01
    • 2016-04-21
    • 1970-01-01
    • 2019-08-12
    • 1970-01-01
    • 2023-02-08
    • 2022-08-18
    相关资源
    最近更新 更多