Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/420.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 保存多个项目时,异步存储无法正常工作_Javascript_Reactjs_React Native - Fatal编程技术网

Javascript 保存多个项目时,异步存储无法正常工作

Javascript 保存多个项目时,异步存储无法正常工作,javascript,reactjs,react-native,Javascript,Reactjs,React Native,我有一个主屏幕,您可以在其中看到以卡片形式显示的多个项目。您可以通过按某个项目查看其详细信息来访问该项目。在详细信息屏幕上,我添加了一个书签选项,使用异步存储保存该项目,您还可以在另一个名为savedItems屏幕的屏幕上检查保存的项目 问题是: 当我为一个项目添加书签时,它会被正确保存,我可以转到savedItems屏幕并在那里找到它,但有时我必须重新加载应用程序才能使该项目显示在savedItems屏幕上,这是为什么 如果我预订了多个项目,它们都会被保存(在console.log上),但

我有一个主屏幕,您可以在其中看到以卡片形式显示的多个项目。您可以通过按某个项目查看其详细信息来访问该项目。在详细信息屏幕上,我添加了一个书签选项,使用异步存储保存该项目,您还可以在另一个名为savedItems屏幕的屏幕上检查保存的项目

问题是:

  • 当我为一个项目添加书签时,它会被正确保存,我可以转到savedItems屏幕并在那里找到它,但有时我必须重新加载应用程序才能使该项目显示在savedItems屏幕上,这是为什么

  • 如果我预订了多个项目,它们都会被保存(在console.log上),但由于某种原因,只有最后一个项目会显示在SavedItems屏幕上,而不会显示超过一个项目

下面是用于book mark的代码片段(在详细信息屏幕上保存了一个项目)

Details.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>
)
如果我预订了多个项目,它们都会被保存(在console.log上),但由于某种原因,只有最后一个项目会显示在SavedItems屏幕上,而不会显示超过一个项目

我认为问题在于,当你保存新项目时,你会删除旧项目。装载
DetailScreen
时,必须阅读旧项目。或者您可以读取onSave方法中的项。这样更安全。这取决于您的应用程序体系结构

const DetailScreen=(道具)=>{
const[items,setItems]=useState(props.route.params);
const onSave=(项目)=>{
让保存=[];
ReadItem(“已保存”)
。然后((res)=>{
如果(res){
saved=JSON.parse(res);
}
const newItems=[…已保存,项];
const items=JSON.stringify(newItems);
SaveItem(“saved”,items)。然后((res)=>{
console.log(“已保存”,res);
});
})
.catch((e)=>console.warn(e));
};
常数goToDetails=()=>{
储蓄([]);
道具。导航。导航(“保存屏幕”);
};
const{width,height}=Dimensions.get(“窗口”);
const{data}=props.route.params;//返回每个项目的数据
//ReadItem(“已保存”)。然后((res)=>console.log(res));
返回(
{
保存(数据);
}}
>
)
当我为一个项目添加书签时,它会被正确保存,我可以转到savedItems屏幕并在那里找到它,但有时我必须重新加载应用程序才能使该项目显示在savedItems屏幕上,这是为什么

我只知道为什么会这样。在某些情况下,您不会卸载
SaveScreen
。当您返回到
保存屏幕时
componentDidMount不会被调用。只需尝试将console.log添加到componentDidMount,如果错过console.log,则当您重现此行为时,意味着您未卸载保存屏幕

要处理所有情况,您可以尝试这样做:

导出默认类详细信息扩展组件{
状态={
已保存:[],
};
removeItem=()=>{
删除项目(“已保存”)
。然后((res)=>{
这是我的国家({
已保存:[],
});
控制台日志(res);
})
.catch((e)=>console.log(e));
};
componentDidMount=()=>{
这是readItems();
this.unsubscribe=navigation.addListener('focus',this.readItems);
};
组件将卸载(){
这个。取消订阅();
}
readItems=()=>{
ReadItem(“已保存”)
。然后((res)=>{
如果(res){
const saved=JSON.parse(res);
这是我的国家({
保存:保存,
});
}
})
.catch((e)=>console.warn(e));
}
render(){…}
}

您好,谢谢您的回复,关于我的第一个问题,我不太清楚在哪里以及如何调用usecallback,您能否详细说明一下,我以前从未使用过它们,关于我的问题的第二个回复,我在componentDidMount中添加了一个console.log,当行为完全按照您提到的方式复制时,它被遗漏了,如何卸载保存屏幕。@Felix我已经更新了示例,您如何读取onSave方法中的项。这是最安全的方法如何从路由器上卸载它所依赖的保存屏幕。我认为您像StackNavigator一样打开了保存屏幕,当您不关闭此屏幕并在保存屏幕上再打开一个时,问题就会重现。我建议您收听事件willMount并阅读其中的项目。我会更新我的回答你是个救命恩人,谢谢你的回答。这很清楚,直截了当
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>
    );
  }
}
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;
  }
}