AsyncStorage не работает должным образом при сохранении нескольких элементов - PullRequest
0 голосов
/ 12 июля 2020

У меня есть главный экран, на котором вы можете видеть несколько элементов, отображаемых в виде карточки, вы можете получить доступ к элементу, нажав его, чтобы увидеть его детали, на экране деталей я добавил опцию закладки, которая сохраняет элемент, используя asyn c хранилище , вы также можете проверить сохраненные элементы на другом экране, который называется экраном savedItems.

Проблема:

  • когда я добавляю элемент в закладки, он сохраняется правильно, и я могу go на экран savedItems и найдите его там, но иногда мне приходится перезагружать приложение, чтобы элемент появился на экране savedItems, почему это так?

  • если я бронирую несколько элементы, которые все они сохраняются (в console.log), но по какой-то причине появляется только последний, я никогда не получаю более одного элемента, отображаемого на экране SavedItems

Сильфон - это фрагменты кода используется для закладки (сохранен элемент на его экране сведений)

Подробности. js

const DetailScreen = (props) => {
  const [saved, setSaved] = useState([]);
  const [items, setItems] = useState(props.route.params);
  const onSave = (item) => {
    const newItems = [...saved, item];

    setSaved(newItems);

    const items = JSON.stringify(newItems);

    SaveItem("saved", items).then((res) => {
      console.log("saved", res);
    });
  };

  const goToDetails = () => {
    setSaved([]);
    props.navigation.navigate("SaveScreen");
  };
  const { width, height } = Dimensions.get("window");
  const { data } = props.route.params; // this returns the data from each article

  //ReadItem("saved").then((res) => console.log(res));
  return (
  <TouchableOpacity
...
                onPress={() => {
                  onSave(data);
                }}
              >
                <MaterialCommunityIcons
                  name="bookmark"
                  size={35}
                  color={colors.shade2}
                />
              </TouchableOpacity>
)

SaveScreen. js

export default class Details extends Component {
  
  state = {
    saved: [],
  };

  removeItem = () => {
    DeleteItem("saved")
      .then((res) => {
        this.setState({
          saved: [],
        });
        console.log(res);
      })
      .catch((e) => console.log(e));
  };

  componentDidMount = () => {
    ReadItem("saved")
      .then((res) => {
        if (res) {
          const saved = JSON.parse(res);
          this.setState({
            saved: saved,
          });
        }
      })
      .catch((e) => console.warn(e));
  };

  render() {
    return (
      <View style={styles.container}>
        <FlatList
          keyExtractor={(item, index) => index.toString()}
          data={this.state.saved}
          renderItem={({ item }) => {
            return (
              <TouchableScale
                activeScale={0.9}
                tension={50}
                friction={7}
                useNativeDriver
                onPress={() =>
                  this.props.navigation.navigate("DetailScreen", { data: item })
                }
              >
                <Card item={item} />
              </TouchableScale>
            );
          }}
        />

        {this.state.saved.length > 0 && (
          <TouchableOpacity onPress={this.removeItem} style={styles.button}>
            <Text style={styles.save}>Remove Key</Text>
          </TouchableOpacity>
        )}
      </View>
    );
  }
}

используемый код сохранить данные с использованием asyn c хранилище

Dbhelper. js

import { AsyncStorage } from "react-native";

export const SaveItem = async (key, value) => {
  try {
    await AsyncStorage.setItem(key, value);
    console.log("saved");
  } catch (e) {
    console.log(e);
  }
};

export const ReadItem = async (key) => {
  try {
    var result = await AsyncStorage.getItem(key);
    return result;
  } catch (e) {
    return e;
  }
};

export function MultiRead(key, onResponse, onFailure) {
  try {
    AsyncStorage.multiGet(key).then((values) => {
      let responseMap = new Map();
      values.map((result, i, data) => {
        let key = data[i][0];
        let value = data[i][1];
        responseMap.set(key, value);
      });
      onResponse(responseMap);
    });
  } catch (error) {
    onFailure(error);
  }
}

export async function DeleteItem(key) {
  try {
    await AsyncStorage.removeItem(key);
    return true;
  } catch (exception) {
    return false;
  }
}

1 Ответ

1 голос
/ 12 июля 2020

если я бронирую несколько элементов, все они сохраняются (в console.log), но по какой-то причине отображается только последний, я никогда не получаю более одного элемента, отображаемого на экране SavedItems

Я думаю, проблема в том, что когда вы сохраняете новый элемент, вы удаляете старые элементы. Вы должны читать старые предметы, когда садитесь на DetailScreen. Или вы можете читать элементы внутри метода onSave. Это больше безопасности. Это зависит от архитектуры вашего приложения

const DetailScreen = (props) => {
  const [items, setItems] = useState(props.route.params);
  
  const onSave = (item) => {
    let saved = [];

    ReadItem("saved")
      .then((res) => {
        if (res) {
          saved = JSON.parse(res);
        }

        const newItems = [...saved, item];
        const items = JSON.stringify(newItems);

        SaveItem("saved", items).then((res) => {
          console.log("saved", res);
        });
      })
      .catch((e) => console.warn(e));
  };


  const goToDetails = () => {
    setSaved([]);
    props.navigation.navigate("SaveScreen");
  };
  const { width, height } = Dimensions.get("window");
  const { data } = props.route.params; // this returns the data from each article

  //ReadItem("saved").then((res) => console.log(res));
  return (
  <TouchableOpacity
...
                onPress={() => {
                  onSave(data);
                }}
              >
                <MaterialCommunityIcons
                  name="bookmark"
                  size={35}
                  color={colors.shade2}
                />
              </TouchableOpacity>
)

, когда я добавляю элемент в закладки, он сохраняется должным образом, и я могу go на экране savedItems и найти его там, но иногда мне приходится перезагружать приложение. для того, чтобы элемент появился на экране savedItems, почему?

У меня есть только одна идея, почему это может произойти. В некоторых случаях вы не размонтируете SaveScreen. При возврате к SaveScreen componentDidMount не вызывается. Просто попробуйте добавить console.log в componentDidMount, и когда вы воспроизводите это поведение, если console.log пропущено, это означает, что вы SaveScreen не отключены

Для обработки всех случаев вы можете попробовать сделать это:

export default class Details extends Component {
  
  state = {
    saved: [],
  };

  removeItem = () => {
    DeleteItem("saved")
      .then((res) => {
        this.setState({
          saved: [],
        });
        console.log(res);
      })
      .catch((e) => console.log(e));
  };

  componentDidMount = () => {
    this.readItems();
    this.unsubscribe = navigation.addListener('focus', this.readItems);
  };

  componentWillUnmount() {
    this.unsubscribe();
  }

  readItems = () => {
    ReadItem("saved")
      .then((res) => {
        if (res) {
          const saved = JSON.parse(res);
          this.setState({
            saved: saved,
          });
        }
      })
      .catch((e) => console.warn(e));
  }

  render() { ... }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...