首页 > 解决方案 > 第一次调用函数后,应用程序中的状态不会改变。需要两次尝试才能改变

问题描述

我有如下代码。我的应用程序从 API 获取加密密码,并在解密后将其复制到剪贴板几秒钟。解密发生在我按下Copy Password按钮的那一刻。但是,当我按下按钮 1 时,我的密码没有被复制到剪贴板,这意味着由于某种原因状态password没有改变。只有在我短时间按 2 次后,密码才会被复制到剪贴板。这背后可能是什么原因?我已经测试了很多案例"dec_password"decPassword在我看来,实际问题发生在组件中,而不是在上下文中。

零件:

import React, { useContext, useEffect } from "react";
import { View, StyleSheet, Text, Clipboard } from "react-native";
import { Context as PasswdDetailContext } from "../context/PasswdDetailContext";
import { Button, Input } from "react-native-elements";
import { decryptRecord } from "../components/Crypto";
import { Context as AuthContext } from "../context/AuthContext";
import { NavigationEvents } from "react-navigation";
import Spacer from "../components/Spacer";

const PasswdDetailScreen = ({ navigation }) => {
  const {
    state: { username, password, domain, description },
    decData,
    decPassword,
    resetPassword,
    reset,
  } = useContext(PasswdDetailContext);
  const {
    state: { secretKey },
  } = useContext(AuthContext);
  const id = navigation.getParam("id");

  const clipboardPasswd = () => {
    Clipboard.setString(password);
    setTimeout(() => {
      Clipboard.setString("");
      resetPassword();
    }, 10000);
  };

  return (
    <>
      <NavigationEvents
        onWillFocus={() => decData({ id, secretKey })}
        onDidBlur={() => {}}
      />
      <Text>Username: {username}</Text>
      <Text>Password: {password}</Text>
      <Text>Description: {description}</Text>
      <Button
        title="Copy Password"
        onPress={() => decPassword({ id, secretKey })}
        onPressIn={() => clipboardPasswd()}
      />
      <Input label="Password" />
    </>
  );
};

const styles = StyleSheet.create({});

export default PasswdDetailScreen;

语境:

import createDataContext from "./createDataContext";
import trackerApi from "../api/tracker";
import { AsyncStorage } from "react-native";
import { decryptRecord } from "../components/Crypto";

const passwdDetailReducer = (state, action) => {
  switch (action.type) {
    case "dec_username":
      return { ...state, username: action.payload };
    case "dec_password":
      return { ...state, password: action.payload };
    case "dec_domain":
      return { ...state, domain: action.payload };
    case "dec_description":
      return { ...state, description: action.payload };
    case "reset_password":
      return { ...state, password: "" };
    case "reset":
      return {};
    default:
      return state;
  }
};

const decData = (dispatch) => async ({ id, secretKey }) => {
  const response = await trackerApi.get("/api/password/" + id + "/");
  var responseUser = response.data.username;
  var responseDesc = response.data.description;
  var decUsername = decryptRecord(responseUser, secretKey);
  var decDescription = decryptRecord(responseDesc, secretKey);
  dispatch({ type: "dec_username", payload: decUsername });
  dispatch({ type: "dec_description", payload: decDescription });
};

const decPassword = (dispatch) => async ({ id, secretKey }) => {
  const response = await trackerApi.get("/api/password/" + id + "/");
  const responsePassword = response.data.password;
  const decPassword = decryptRecord(responsePassword, secretKey);
  dispatch({ type: "dec_password", payload: decPassword });
};

const resetPassword = (dispatch) => () => {
  dispatch({ type: "reset_password" });
};

const reset = (dispatch) => () => {
  dispatch({ type: "reset" });
};

export const { Provider, Context } = createDataContext(
  passwdDetailReducer,
  { decData, decPassword, reset, resetPassword },
  { username: "", password: "", domain: "", description: "" }
);

标签: reactjsreact-nativereact-reduxexpo

解决方案


您想监听密码的更改,并且仅在密码不为空时复制。您可能还希望在单击按钮时禁用该按钮。

import React, { useContext, useEffect } from "react";
import { View, StyleSheet, Text, Clipboard } from "react-native";
import { Context as PasswdDetailContext } from "../context/PasswdDetailContext";
import { Button, Input } from "react-native-elements";
import { decryptRecord } from "../components/Crypto";
import { Context as AuthContext } from "../context/AuthContext";
import { NavigationEvents } from "react-navigation";
import Spacer from "../components/Spacer";

const PasswdDetailScreen = ({ navigation }) => {
  const {
    state: { username, password, domain, description },
    decData,
    decPassword,
    resetPassword,
    reset,
  } = useContext(PasswdDetailContext);
  const {
    state: { secretKey },
  } = useContext(AuthContext);
  const id = navigation.getParam("id");

  const clipboardPasswd = () => {
    Clipboard.setString(password);
    setTimeout(() => {
      Clipboard.setString("");
      resetPassword();
    }, 10000);
  };
  useEffect(()=>{
     if (password !== '') clipboardPasswd();
  },[password]);

  return (
    <>
      <NavigationEvents
        onWillFocus={() => decData({ id, secretKey })}
        onDidBlur={() => {}}
      />
      <Text>Username: {username}</Text>
      <Text>Password: {password}</Text>
      <Text>Description: {description}</Text>
      <Button
        title="Copy Password"
        onPress={() => decPassword({ id, secretKey })}
      />
      <Input label="Password" />
    </>
  );
};

const styles = StyleSheet.create({});

export default PasswdDetailScreen;

推荐阅读