简体   繁体   中英

Saving data into async storage onPress in react native

Am trying to save data into async storage every time a user clicks on a certain button and then have the saved data displayed on a seprate screen that i can navigate to, i found an example doing the same thing but using class components, i started learning react native using functional components only so i have no idea to transition from the class component to the functional component in this case

The code used: ( the screen doing the saving )

import React from "react";
import { StyleSheet, Text, View, Dimensions, Image } from "react-native";
import { SharedElement } from "react-native-shared-element";
import { TouchableOpacity, ScrollView } from "react-native-gesture-handler";
import MaterialCommunityIcons from "react-native-vector-icons/MaterialCommunityIcons";
import { Entypo } from "@expo/vector-icons";
import { FontAwesome } from "@expo/vector-icons";
import colors from "../config/colors";
import { SaveItem, ReadItem } from "../components/DbHelper";
const DetailScreen = (props) => {
  state = {       ####### getting an error on state 
    items: props.route.params,
    saved: [],
  };
  onSave = (item) => {
    const { saved } = this.state;
    const newItems = [...saved, item];

    this.setState({
      saved: newItems,
    });

    const items = JSON.stringify(newItems);

    SaveItem("saved", items)
      .then((res) => {
        console.warn("saved", res);
      })
      .catch((e) => console.warn(e));
  };
  goToDetails = () => {
    this.setState({
      saved: [],
    });

    this.props.navigation.navigate("SaveScreen");
  };
  const { width, height } = Dimensions.get("window");
  const { data } = props.route.params;

  return (
    <View style={styles.container}>
      <View>
        <SharedElement id={`item.${data.id}.photo`}>
          <Image
            resizeMode="cover"
            source={{ uri: data.img }}
            style={{
              width: 400,
              height: 300,
              borderBottomLeftRadius: 50,
              //borderBottomRightRadius: 50,
            }}
          />
        </SharedElement>
        <View
          style={{
            flexDirection: "row",
            alignItems: "center",
            position: "absolute",
            bottom: 14,
            left: 10,
          }}
        >
          <SharedElement id={`item.${data.id}.profilePic`}>
            <Image
              resizeMode="cover"
              source={{ uri: data.image }}
              style={{
                width: 60,
                height: 60,
                borderRadius: 10,
                marginRight: 14,
              }}
            />
          </SharedElement>
          <View
            style={{
              flex: 1,
              flexDirection: "row",
              alignItems: "center",
              justifyContent: "space-between",
            }}
          >
            <SharedElement id={`item.${data.id}.profilePic`}>
              <Image
                resizeMode="cover"
                source={{
                  uri:
                    "https://fertility.womenandinfants.org/app/uploads/photo-huff-post-logo.png",
                }}
                style={styles.blogProfilePic}
              />
            </SharedElement>
            <View>
              <SharedElement id={`item.${data.id}.username`}>
                <Text
                  style={{ color: "white", fontSize: 16, fontWeight: "bold" }}
                >
                  {data.username}
                </Text>
              </SharedElement>
              <View
                style={{
                  flexDirection: "row",
                  alignItems: "center",
                }}
              >
                <SharedElement id={`item.${data.id}.username`}>
                  {data.author != null ? (
                    <Text style={styles.blogUsername}>{data.author}</Text>
                  ) : (
                    <Text style={styles.blogUsername}>Anonymous author</Text>
                  )}
                </SharedElement>

                <SharedElement id={`item.${data.id}.readtime`}>
                  <View style={{ bottom: 5 }}>
                    <Entypo
                      name="time-slot"
                      size={20}
                      color={colors.shade2}
                      style={{ top: 84, right: 210 }}
                    />
                    <Text style={styles.readtime}>
                      {data.content.length / 10}min
                    </Text>
                  </View>
                </SharedElement>
              </View>
            </View>

            <View style={{ right: 20 }}>
              <TouchableOpacity
                onPress={() => {
                  this.onSave(item);
                }}
              >
                <MaterialCommunityIcons
                  name="bookmark"
                  size={35}
                  color={colors.shade2}
                />
              </TouchableOpacity>
              <TouchableOpacity
                onPress={this.goToDetails}
                style={styles.button}
              >
                <Text style={styles.save}>View Saved</Text>
              </TouchableOpacity>
            </View>
          </View>
        </View>
        <SharedElement id={`item.${data.id}.readtime`}>
          <Text
            style={{
              color: "white",
              fontSize: 14,
              borderColor: "red",
              borderRadius: 10,
              top: 45,
              left: 280,
            }}
          >
            {data.category}
          </Text>
        </SharedElement>
      </View>
      <ScrollView style={{ paddingHorizontal: 10, paddingTop: 14 }}>
        <SharedElement
          id={`item.${data.id}.text`}
          style={{ width: width - 30, marginBottom: 14 }}
        >
          <Text
            style={{
              fontSize: 26,
              fontWeight: "bold",
              lineHeight: 32,
              color: "#FFFFFF",
              top: 50,
            }}
          >
            {data.title}
          </Text>
        </SharedElement>
        <Text
          style={{
            fontSize: 16,
            lineHeight: 28,
            textAlign: "justify",
            opacity: 0.5,
            color: "#CDCFDE",
            top: 50,
          }}
        >
          {data.content}
        </Text>

        <View
          style={{
            marginVertical: 25,
            paddingBottom: 20,
            flex: 1,
            flexDirection: "row",
            justifyContent: "space-between",
            alignItems: "center",
          }}
        >
          <TouchableOpacity
            style={{ flexDirection: "row", padding: 12, alignItems: "center" }}
          >
            {/*      <Feather name="heart" size={16} color="orange" />
            <Text style={{ marginHorizontal: 10 }}>3.4k Likes</Text>*/}
          </TouchableOpacity>
        </View>
      </ScrollView>
      <View style={{ position: "absolute", top: 40, left: 10 }}>
        <TouchableOpacity onPress={() => props.navigation.goBack()}>
          <FontAwesome name="arrow-circle-left" size={30} color="white" />
        </TouchableOpacity>
      </View>
    </View>
  );
};

});
export default DetailScreen;

The code for storing the data:

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;
  }
}

Sorry for the long code i tried to include all the parts to have a better grasp of the problem.

Your are using this in on non-class component

instead of declaring state you should use hooks You will need to remove all this occurences to use hooks correctly

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

 onSave = (item) => {
  // do this
  const newItems = [...saved, item]
  setSaved(newItems)
  // or, better, this
  setSaved(prev => [...prev, item])
  // ...

I'll recommend you go through react and react-native documentation to help you understand how to work with class and functional components. This is important, as it will help get ahold of why and how things work.

Now going to your code, there are three things you need to address to get your code working;

  1. To access state in functional components, you'll have to use hooks(eg useState).
  2. The this property is not available in functional components.
  3. Declare your functions.

Update to your code

import React, {useState} from 'react';

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.warn("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;

React: https://reactjs.org/docs/getting-started.html React Native: https://reactnative.dev/docs/intro-react

you need to convert class based state code into hooks based approach using useState

for instance you class methods will look like this:

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

    setSaved(newItems);

    const items = JSON.stringify(newItems);

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

  goToDetails = () => {
    setSaved([]);
    props.navigation.navigate("SaveScreen");
  };

for more info see this: reactdocs

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM